move elementary to trunk base. out of TMP/st.
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 29 Jan 2011 03:36:15 +0000 (03:36 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 29 Jan 2011 03:36:15 +0000 (03:36 +0000)
git-svn-id: https://svn.enlightenment.org/svn/e/trunk/elementary@56356 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

535 files changed:
.gitignore [new file with mode: 0644]
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
config/Makefile.am [new file with mode: 0644]
config/default/Makefile.am [new file with mode: 0644]
config/default/base.src [new file with mode: 0644]
config/default/icon.png [new file with mode: 0644]
config/default/profile.desktop [new file with mode: 0644]
config/illume/Makefile.am [new file with mode: 0644]
config/illume/base.src [new file with mode: 0644]
config/illume/icon.png [new file with mode: 0644]
config/illume/profile.desktop [new file with mode: 0644]
config/profile.src [new file with mode: 0644]
config/standard/Makefile.am [new file with mode: 0644]
config/standard/base.src [new file with mode: 0644]
config/standard/icon.png [new file with mode: 0644]
config/standard/profile.desktop [new file with mode: 0644]
configure.ac [new file with mode: 0644]
data/.cvsignore [new file with mode: 0644]
data/Makefile.am [new file with mode: 0644]
data/desktop/Makefile.am [new file with mode: 0644]
data/desktop/elementary.png [new file with mode: 0644]
data/desktop/elementary_config.desktop [new file with mode: 0644]
data/desktop/elementary_test.desktop [new file with mode: 0644]
data/edje_externals/Makefile.am [new file with mode: 0644]
data/edje_externals/ico_anchorblock.png [new file with mode: 0644]
data/edje_externals/ico_anchorview.png [new file with mode: 0644]
data/edje_externals/ico_bubble.png [new file with mode: 0644]
data/edje_externals/ico_button.png [new file with mode: 0644]
data/edje_externals/ico_check.png [new file with mode: 0644]
data/edje_externals/ico_clock.png [new file with mode: 0644]
data/edje_externals/ico_fileselector.png [new file with mode: 0644]
data/edje_externals/ico_fileselector_button.png [new file with mode: 0644]
data/edje_externals/ico_genlist.png [new file with mode: 0644]
data/edje_externals/ico_hoversel.png [new file with mode: 0644]
data/edje_externals/ico_list.png [new file with mode: 0755]
data/edje_externals/ico_map.png [new file with mode: 0644]
data/edje_externals/ico_notepad.png [new file with mode: 0644]
data/edje_externals/ico_photocam.png [new file with mode: 0644]
data/edje_externals/ico_progressbar.png [new file with mode: 0644]
data/edje_externals/ico_radio.png [new file with mode: 0644]
data/edje_externals/ico_scrolled_entry.png [new file with mode: 0644]
data/edje_externals/ico_slider.png [new file with mode: 0644]
data/edje_externals/ico_slideshow.png [new file with mode: 0644]
data/edje_externals/ico_spinner.png [new file with mode: 0644]
data/edje_externals/ico_thumb.png [new file with mode: 0644]
data/edje_externals/ico_toggle.png [new file with mode: 0644]
data/edje_externals/ico_toolbar.png [new file with mode: 0644]
data/edje_externals/icons.edc [new file with mode: 0644]
data/images/Makefile.am [new file with mode: 0644]
data/images/bubble.png [new file with mode: 0644]
data/images/bubble_sh.png [new file with mode: 0644]
data/images/icon_00.png [new file with mode: 0644]
data/images/icon_01.png [new file with mode: 0644]
data/images/icon_02.png [new file with mode: 0644]
data/images/icon_03.png [new file with mode: 0644]
data/images/icon_04.png [new file with mode: 0644]
data/images/icon_05.png [new file with mode: 0644]
data/images/icon_06.png [new file with mode: 0644]
data/images/icon_07.png [new file with mode: 0644]
data/images/icon_08.png [new file with mode: 0644]
data/images/icon_09.png [new file with mode: 0644]
data/images/icon_10.png [new file with mode: 0644]
data/images/icon_11.png [new file with mode: 0644]
data/images/icon_12.png [new file with mode: 0644]
data/images/icon_13.png [new file with mode: 0644]
data/images/icon_14.png [new file with mode: 0644]
data/images/icon_15.png [new file with mode: 0644]
data/images/icon_16.png [new file with mode: 0644]
data/images/icon_17.png [new file with mode: 0644]
data/images/icon_18.png [new file with mode: 0644]
data/images/icon_19.png [new file with mode: 0644]
data/images/icon_20.png [new file with mode: 0644]
data/images/icon_21.png [new file with mode: 0644]
data/images/icon_22.png [new file with mode: 0644]
data/images/icon_23.png [new file with mode: 0644]
data/images/logo.png [new file with mode: 0644]
data/images/logo_small.png [new file with mode: 0644]
data/images/mystrale.jpg [new file with mode: 0644]
data/images/mystrale_2.jpg [new file with mode: 0644]
data/images/panel_01.jpg [new file with mode: 0644]
data/images/parking.png [new file with mode: 0644]
data/images/plant_01.jpg [new file with mode: 0644]
data/images/rock_01.jpg [new file with mode: 0644]
data/images/rock_02.jpg [new file with mode: 0644]
data/images/sky_01.jpg [new file with mode: 0644]
data/images/sky_02.jpg [new file with mode: 0644]
data/images/sky_03.jpg [new file with mode: 0644]
data/images/sky_04.jpg [new file with mode: 0644]
data/images/wood_01.jpg [new file with mode: 0644]
data/objects/Makefile.am [new file with mode: 0644]
data/objects/clo.png [new file with mode: 0644]
data/objects/colorpreview.edc [new file with mode: 0644]
data/objects/cross.png [new file with mode: 0644]
data/objects/cursors.edc [new file with mode: 0644]
data/objects/font_preview.edc [new file with mode: 0644]
data/objects/grid_bg.png [new file with mode: 0644]
data/objects/multip.edc [new file with mode: 0644]
data/objects/over.png [new file with mode: 0644]
data/objects/sky.jpg [new file with mode: 0644]
data/objects/test.edc [new file with mode: 0644]
data/objects/under.png [new file with mode: 0644]
data/themes/Makefile.am [new file with mode: 0644]
data/themes/arrow_down.png [new file with mode: 0644]
data/themes/arrow_down.xcf.gz [new file with mode: 0644]
data/themes/arrow_left.png [new file with mode: 0644]
data/themes/arrow_right.png [new file with mode: 0644]
data/themes/arrow_up.png [new file with mode: 0644]
data/themes/arrow_up.xcf.gz [new file with mode: 0644]
data/themes/bar_shine.png [new file with mode: 0644]
data/themes/black.png [new file with mode: 0644]
data/themes/bt_base1.png [new file with mode: 0644]
data/themes/bt_base2.png [new file with mode: 0644]
data/themes/bt_bases.png [new file with mode: 0644]
data/themes/bt_basew.png [new file with mode: 0644]
data/themes/bt_dis_base.png [new file with mode: 0644]
data/themes/bt_dis_hilight.png [new file with mode: 0644]
data/themes/bt_dis_shine.png [new file with mode: 0644]
data/themes/bt_glow.png [new file with mode: 0644]
data/themes/bt_hilight.png [new file with mode: 0644]
data/themes/bt_hilightw.png [new file with mode: 0644]
data/themes/bt_shine.png [new file with mode: 0644]
data/themes/bt_sm_base1.png [new file with mode: 0644]
data/themes/bt_sm_base2.png [new file with mode: 0644]
data/themes/bt_sm_hilight.png [new file with mode: 0644]
data/themes/bt_sm_shine.png [new file with mode: 0644]
data/themes/bt_spinner_down.png [new file with mode: 0644]
data/themes/bt_spinner_hilight.png [new file with mode: 0644]
data/themes/bt_spinner_up.png [new file with mode: 0644]
data/themes/bubble.png [new file with mode: 0644]
data/themes/bubble_1.png [new file with mode: 0644]
data/themes/bubble_2.png [new file with mode: 0644]
data/themes/bubble_3.png [new file with mode: 0644]
data/themes/bubble_4.png [new file with mode: 0644]
data/themes/bubble_shine.png [new file with mode: 0644]
data/themes/bubble_shine3.png [new file with mode: 0644]
data/themes/bubble_shine4.png [new file with mode: 0644]
data/themes/busy-1.png [new file with mode: 0644]
data/themes/busy-2.png [new file with mode: 0644]
data/themes/busy-3.png [new file with mode: 0644]
data/themes/busy-4.png [new file with mode: 0644]
data/themes/busy-5.png [new file with mode: 0644]
data/themes/busy-6.png [new file with mode: 0644]
data/themes/busy-7.png [new file with mode: 0644]
data/themes/busy-8.png [new file with mode: 0644]
data/themes/busy-9.png [new file with mode: 0644]
data/themes/check.png [new file with mode: 0644]
data/themes/check2.png [new file with mode: 0644]
data/themes/check_base.png [new file with mode: 0644]
data/themes/color_picker_alpha.png [new file with mode: 0644]
data/themes/color_picker_alpha_bg.png [new file with mode: 0644]
data/themes/color_picker_brightness.png [new file with mode: 0644]
data/themes/color_picker_color.png [new file with mode: 0644]
data/themes/color_picker_opacity.png [new file with mode: 0644]
data/themes/cur_box.png [new file with mode: 0644]
data/themes/cur_glow.png [new file with mode: 0644]
data/themes/cur_hi.png [new file with mode: 0644]
data/themes/cur_shad.png [new file with mode: 0644]
data/themes/cur_shine.png [new file with mode: 0644]
data/themes/default-desktop.edc [new file with mode: 0644]
data/themes/default.edc [new file with mode: 0644]
data/themes/dia_botshad.png [new file with mode: 0644]
data/themes/dia_grad.png [new file with mode: 0644]
data/themes/dia_topshad.png [new file with mode: 0644]
data/themes/down.png [new file with mode: 0644]
data/themes/emo-angry-shout.png [new file with mode: 0644]
data/themes/emo-angry.png [new file with mode: 0644]
data/themes/emo-crazy-laugh.png [new file with mode: 0644]
data/themes/emo-evil-laugh.png [new file with mode: 0644]
data/themes/emo-evil.png [new file with mode: 0644]
data/themes/emo-goggle-smile.png [new file with mode: 0644]
data/themes/emo-grumpy-smile.png [new file with mode: 0644]
data/themes/emo-grumpy.png [new file with mode: 0644]
data/themes/emo-guilty-smile.png [new file with mode: 0644]
data/themes/emo-guilty.png [new file with mode: 0644]
data/themes/emo-haha.png [new file with mode: 0644]
data/themes/emo-half-smile.png [new file with mode: 0644]
data/themes/emo-happy-panting.png [new file with mode: 0644]
data/themes/emo-happy.png [new file with mode: 0644]
data/themes/emo-indifferent.png [new file with mode: 0644]
data/themes/emo-kiss.png [new file with mode: 0644]
data/themes/emo-knowing-grin.png [new file with mode: 0644]
data/themes/emo-laugh.png [new file with mode: 0644]
data/themes/emo-little-bit-sorry.png [new file with mode: 0644]
data/themes/emo-love-lots.png [new file with mode: 0644]
data/themes/emo-love.png [new file with mode: 0644]
data/themes/emo-minimal-smile.png [new file with mode: 0644]
data/themes/emo-not-happy.png [new file with mode: 0644]
data/themes/emo-not-impressed.png [new file with mode: 0644]
data/themes/emo-omg.png [new file with mode: 0644]
data/themes/emo-opensmile.png [new file with mode: 0644]
data/themes/emo-smile.png [new file with mode: 0644]
data/themes/emo-sorry.png [new file with mode: 0644]
data/themes/emo-squint-laugh.png [new file with mode: 0644]
data/themes/emo-surprised.png [new file with mode: 0644]
data/themes/emo-suspicious.png [new file with mode: 0644]
data/themes/emo-tongue-dangling.png [new file with mode: 0644]
data/themes/emo-tongue-poke.png [new file with mode: 0644]
data/themes/emo-uh.png [new file with mode: 0644]
data/themes/emo-unhappy.png [new file with mode: 0644]
data/themes/emo-very-sorry.png [new file with mode: 0644]
data/themes/emo-what.png [new file with mode: 0644]
data/themes/emo-wink.png [new file with mode: 0644]
data/themes/emo-worried.png [new file with mode: 0644]
data/themes/emo-wtf.png [new file with mode: 0644]
data/themes/flip.xcf.gz [new file with mode: 0644]
data/themes/flip_0b.png [new file with mode: 0644]
data/themes/flip_0t.png [new file with mode: 0644]
data/themes/flip_1b.png [new file with mode: 0644]
data/themes/flip_1t.png [new file with mode: 0644]
data/themes/flip_2b.png [new file with mode: 0644]
data/themes/flip_2t.png [new file with mode: 0644]
data/themes/flip_3b.png [new file with mode: 0644]
data/themes/flip_3t.png [new file with mode: 0644]
data/themes/flip_4b.png [new file with mode: 0644]
data/themes/flip_4t.png [new file with mode: 0644]
data/themes/flip_5b.png [new file with mode: 0644]
data/themes/flip_5t.png [new file with mode: 0644]
data/themes/flip_6b.png [new file with mode: 0644]
data/themes/flip_6t.png [new file with mode: 0644]
data/themes/flip_7b.png [new file with mode: 0644]
data/themes/flip_7t.png [new file with mode: 0644]
data/themes/flip_8b.png [new file with mode: 0644]
data/themes/flip_8t.png [new file with mode: 0644]
data/themes/flip_9b.png [new file with mode: 0644]
data/themes/flip_9t.png [new file with mode: 0644]
data/themes/flip_amb.png [new file with mode: 0644]
data/themes/flip_amt.png [new file with mode: 0644]
data/themes/flip_b.png [new file with mode: 0644]
data/themes/flip_base.png [new file with mode: 0644]
data/themes/flip_base_shad.png [new file with mode: 0644]
data/themes/flip_pmb.png [new file with mode: 0644]
data/themes/flip_pmt.png [new file with mode: 0644]
data/themes/flip_shad.png [new file with mode: 0644]
data/themes/flip_t.png [new file with mode: 0644]
data/themes/frame_1.png [new file with mode: 0644]
data/themes/frame_2.png [new file with mode: 0644]
data/themes/group_index.png [new file with mode: 0644]
data/themes/head.png [new file with mode: 0644]
data/themes/hoversel_entry_bg.png [new file with mode: 0644]
data/themes/icon_apps.png [new file with mode: 0644]
data/themes/icon_arrow_down.png [new file with mode: 0644]
data/themes/icon_arrow_down_left.png [new file with mode: 0644]
data/themes/icon_arrow_down_right.png [new file with mode: 0644]
data/themes/icon_arrow_left.png [new file with mode: 0644]
data/themes/icon_arrow_right.png [new file with mode: 0644]
data/themes/icon_arrow_up.png [new file with mode: 0644]
data/themes/icon_arrow_up_left.png [new file with mode: 0644]
data/themes/icon_arrow_up_right.png [new file with mode: 0644]
data/themes/icon_chat.png [new file with mode: 0644]
data/themes/icon_clock.png [new file with mode: 0644]
data/themes/icon_close.png [new file with mode: 0644]
data/themes/icon_delete.png [new file with mode: 0644]
data/themes/icon_edit.png [new file with mode: 0644]
data/themes/icon_file.png [new file with mode: 0644]
data/themes/icon_folder.png [new file with mode: 0644]
data/themes/icon_home.png [new file with mode: 0644]
data/themes/icon_left_arrow.png [new file with mode: 0644]
data/themes/icon_refresh.png [new file with mode: 0644]
data/themes/icon_right_arrow.png [new file with mode: 0644]
data/themes/ilist_1.png [new file with mode: 0644]
data/themes/ilist_1_h.png [new file with mode: 0644]
data/themes/ilist_2.png [new file with mode: 0644]
data/themes/ilist_2_h.png [new file with mode: 0644]
data/themes/ilist_item_shadow.png [new file with mode: 0644]
data/themes/ilist_item_shadow_h.png [new file with mode: 0644]
data/themes/leftright.png [new file with mode: 0644]
data/themes/map_item.png [new file with mode: 0644]
data/themes/map_item_1.png [new file with mode: 0644]
data/themes/map_item_2.png [new file with mode: 0644]
data/themes/outdent-bottom.png [new file with mode: 0644]
data/themes/outdent-top.png [new file with mode: 0644]
data/themes/radio.png [new file with mode: 0644]
data/themes/radio2.png [new file with mode: 0644]
data/themes/radio_base.png [new file with mode: 0644]
data/themes/sb_runnerh.png [new file with mode: 0644]
data/themes/sb_runnerv.png [new file with mode: 0644]
data/themes/separator_h.png [new file with mode: 0644]
data/themes/separator_v.png [new file with mode: 0644]
data/themes/shad_circ.png [new file with mode: 0644]
data/themes/shadow.png [new file with mode: 0644]
data/themes/shelf_inset.png [new file with mode: 0644]
data/themes/sl_bg.png [new file with mode: 0644]
data/themes/sl_bg_over.png [new file with mode: 0644]
data/themes/sl_bt2_0_0.png [new file with mode: 0644]
data/themes/sl_bt2_0_1.png [new file with mode: 0644]
data/themes/sl_bt2_0_2.png [new file with mode: 0644]
data/themes/sl_bt2_1.png [new file with mode: 0644]
data/themes/sl_bt2_2.png [new file with mode: 0644]
data/themes/sl_bt_0.png [new file with mode: 0644]
data/themes/sl_bt_1.png [new file with mode: 0644]
data/themes/sl_bt_2.png [new file with mode: 0644]
data/themes/sl_bt_3.png [new file with mode: 0644]
data/themes/sl_units.png [new file with mode: 0644]
data/themes/slv_bg.png [new file with mode: 0644]
data/themes/slv_bg_over.png [new file with mode: 0644]
data/themes/slv_units.png [new file with mode: 0644]
data/themes/sp_bt_l.png [new file with mode: 0644]
data/themes/sp_bt_r.png [new file with mode: 0644]
data/themes/thumb_shadow.png [new file with mode: 0644]
data/themes/tog_base.png [new file with mode: 0644]
data/themes/tog_dis_base.png [new file with mode: 0644]
data/themes/toolbar_sel.png [new file with mode: 0644]
data/themes/toolbar_separator_v.png [new file with mode: 0644]
data/themes/tooltip-base.png [new file with mode: 0644]
data/themes/tooltip-corner-bottom-left-tip.png [new file with mode: 0644]
data/themes/tooltip-corner-bottom-right-tip.png [new file with mode: 0644]
data/themes/tooltip-corner-top-left-tip.png [new file with mode: 0644]
data/themes/tooltip-corner-top-right-tip.png [new file with mode: 0644]
data/themes/tooltip-edge-bottom-tip.png [new file with mode: 0644]
data/themes/tooltip-edge-left-tip.png [new file with mode: 0644]
data/themes/tooltip-edge-right-tip.png [new file with mode: 0644]
data/themes/tooltip-edge-top-tip.png [new file with mode: 0644]
data/themes/up.png [new file with mode: 0644]
data/themes/updown.png [new file with mode: 0644]
doc/.cvsignore [new file with mode: 0644]
doc/Doxyfile [new file with mode: 0644]
doc/Makefile.am [new file with mode: 0644]
doc/e.css [new file with mode: 0644]
doc/elementary.dox.in [new file with mode: 0644]
doc/foot.html [new file with mode: 0644]
doc/head.html [new file with mode: 0644]
doc/img/edoxy.css [new file with mode: 0644]
doc/img/elementary.png [new file with mode: 0644]
doc/img/foot_bg.png [new file with mode: 0644]
doc/img/head_bg.png [new file with mode: 0644]
doc/img/header_menu_background.png [new file with mode: 0644]
doc/img/header_menu_background_last.png [new file with mode: 0644]
doc/img/header_menu_current_background.png [new file with mode: 0644]
doc/img/header_menu_unselected_background.png [new file with mode: 0644]
doc/img/logo.png [new file with mode: 0644]
elementary.pc.in [new file with mode: 0644]
elementary.spec.in [new file with mode: 0644]
m4/ac_attribute.m4 [new file with mode: 0644]
m4/efl_binary.m4 [new file with mode: 0644]
m4/efl_doxygen.m4 [new file with mode: 0644]
m4/efl_threads.m4 [new file with mode: 0644]
src/.cvsignore [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/bin/.cvsignore [new file with mode: 0644]
src/bin/Makefile.am [new file with mode: 0644]
src/bin/config.c [new file with mode: 0644]
src/bin/quicklaunch.c [new file with mode: 0644]
src/bin/run.c [new file with mode: 0644]
src/bin/test.c [new file with mode: 0644]
src/bin/test_actionslider.c [new file with mode: 0644]
src/bin/test_anchorblock.c [new file with mode: 0644]
src/bin/test_anchorview.c [new file with mode: 0644]
src/bin/test_anim.c [new file with mode: 0644]
src/bin/test_bg.c [new file with mode: 0644]
src/bin/test_box.c [new file with mode: 0644]
src/bin/test_bubble.c [new file with mode: 0644]
src/bin/test_button.c [new file with mode: 0644]
src/bin/test_calendar.c [new file with mode: 0644]
src/bin/test_check.c [new file with mode: 0644]
src/bin/test_clock.c [new file with mode: 0644]
src/bin/test_colorselector.c [new file with mode: 0644]
src/bin/test_conform.c [new file with mode: 0644]
src/bin/test_ctxpopup.c [new file with mode: 0644]
src/bin/test_cursor.c [new file with mode: 0644]
src/bin/test_diskselector.c [new file with mode: 0644]
src/bin/test_entry.c [new file with mode: 0644]
src/bin/test_fileselector.c [new file with mode: 0644]
src/bin/test_fileselector_button.c [new file with mode: 0644]
src/bin/test_fileselector_entry.c [new file with mode: 0644]
src/bin/test_flip.c [new file with mode: 0644]
src/bin/test_flipselector.c [new file with mode: 0644]
src/bin/test_floating.c [new file with mode: 0644]
src/bin/test_focus.c [new file with mode: 0644]
src/bin/test_focus2.c [new file with mode: 0644]
src/bin/test_gengrid.c [new file with mode: 0644]
src/bin/test_genlist.c [new file with mode: 0644]
src/bin/test_hover.c [new file with mode: 0644]
src/bin/test_hoversel.c [new file with mode: 0644]
src/bin/test_icon.c [new file with mode: 0644]
src/bin/test_icon_desktops.c [new file with mode: 0644]
src/bin/test_index.c [new file with mode: 0644]
src/bin/test_inwin.c [new file with mode: 0644]
src/bin/test_label.c [new file with mode: 0644]
src/bin/test_launcher.c [new file with mode: 0644]
src/bin/test_layout.c [new file with mode: 0644]
src/bin/test_list.c [new file with mode: 0644]
src/bin/test_map.c [new file with mode: 0644]
src/bin/test_menu.c [new file with mode: 0644]
src/bin/test_multi.c [new file with mode: 0644]
src/bin/test_notify.c [new file with mode: 0644]
src/bin/test_pager.c [new file with mode: 0644]
src/bin/test_panel.c [new file with mode: 0644]
src/bin/test_panes.c [new file with mode: 0644]
src/bin/test_photo.c [new file with mode: 0644]
src/bin/test_photocam.c [new file with mode: 0644]
src/bin/test_progressbar.c [new file with mode: 0644]
src/bin/test_radio.c [new file with mode: 0644]
src/bin/test_scaling.c [new file with mode: 0644]
src/bin/test_scroller.c [new file with mode: 0644]
src/bin/test_separator.c [new file with mode: 0644]
src/bin/test_slider.c [new file with mode: 0644]
src/bin/test_slideshow.c [new file with mode: 0644]
src/bin/test_spinner.c [new file with mode: 0644]
src/bin/test_store.c [new file with mode: 0644]
src/bin/test_table.c [new file with mode: 0644]
src/bin/test_thumb.c [new file with mode: 0644]
src/bin/test_toggle.c [new file with mode: 0644]
src/bin/test_toolbar.c [new file with mode: 0644]
src/bin/test_tooltip.c [new file with mode: 0644]
src/bin/test_transit.c [new file with mode: 0644]
src/bin/test_weather.c [new file with mode: 0644]
src/bin/test_win_state.c [new file with mode: 0644]
src/edje_externals/Makefile.am [new file with mode: 0644]
src/edje_externals/elm.c [new file with mode: 0644]
src/edje_externals/elm_anchorblock.c [new file with mode: 0644]
src/edje_externals/elm_anchorview.c [new file with mode: 0644]
src/edje_externals/elm_bubble.c [new file with mode: 0644]
src/edje_externals/elm_button.c [new file with mode: 0644]
src/edje_externals/elm_check.c [new file with mode: 0644]
src/edje_externals/elm_clock.c [new file with mode: 0644]
src/edje_externals/elm_fileselector.c [new file with mode: 0644]
src/edje_externals/elm_fileselector_button.c [new file with mode: 0644]
src/edje_externals/elm_fileselector_entry.c [new file with mode: 0644]
src/edje_externals/elm_genlist.c [new file with mode: 0644]
src/edje_externals/elm_hoversel.c [new file with mode: 0644]
src/edje_externals/elm_icon.c [new file with mode: 0644]
src/edje_externals/elm_label.c [new file with mode: 0644]
src/edje_externals/elm_list.c [new file with mode: 0644]
src/edje_externals/elm_map.c [new file with mode: 0644]
src/edje_externals/elm_notify.c [new file with mode: 0644]
src/edje_externals/elm_panes.c [new file with mode: 0644]
src/edje_externals/elm_photocam.c [new file with mode: 0644]
src/edje_externals/elm_progressbar.c [new file with mode: 0644]
src/edje_externals/elm_radio.c [new file with mode: 0644]
src/edje_externals/elm_scrolled_entry.c [new file with mode: 0644]
src/edje_externals/elm_scroller.c [new file with mode: 0644]
src/edje_externals/elm_slider.c [new file with mode: 0644]
src/edje_externals/elm_slideshow.c [new file with mode: 0644]
src/edje_externals/elm_spinner.c [new file with mode: 0644]
src/edje_externals/elm_thumb.c [new file with mode: 0644]
src/edje_externals/elm_toggle.c [new file with mode: 0644]
src/edje_externals/elm_toolbar.c [new file with mode: 0644]
src/edje_externals/modules.inc [new file with mode: 0644]
src/edje_externals/private.h [new file with mode: 0644]
src/lib/Elementary.h.in [new file with mode: 0644]
src/lib/Elementary_Cursor.h [new file with mode: 0644]
src/lib/Makefile.am [new file with mode: 0644]
src/lib/elc_anchorblock.c [new file with mode: 0644]
src/lib/elc_anchorview.c [new file with mode: 0644]
src/lib/elc_ctxpopup.c [new file with mode: 0644]
src/lib/elc_fileselector.c [new file with mode: 0644]
src/lib/elc_fileselector_button.c [new file with mode: 0644]
src/lib/elc_fileselector_entry.c [new file with mode: 0644]
src/lib/elc_hoversel.c [new file with mode: 0644]
src/lib/elc_scrolled_entry.c [new file with mode: 0644]
src/lib/elm_actionslider.c [new file with mode: 0644]
src/lib/elm_animator.c [new file with mode: 0644]
src/lib/elm_bg.c [new file with mode: 0644]
src/lib/elm_box.c [new file with mode: 0644]
src/lib/elm_bubble.c [new file with mode: 0644]
src/lib/elm_button.c [new file with mode: 0644]
src/lib/elm_calendar.c [new file with mode: 0644]
src/lib/elm_check.c [new file with mode: 0644]
src/lib/elm_clock.c [new file with mode: 0644]
src/lib/elm_cnp_helper.c [new file with mode: 0644]
src/lib/elm_colorselector.c [new file with mode: 0644]
src/lib/elm_config.c [new file with mode: 0644]
src/lib/elm_conform.c [new file with mode: 0644]
src/lib/elm_diskselector.c [new file with mode: 0644]
src/lib/elm_entry.c [new file with mode: 0644]
src/lib/elm_flip.c [new file with mode: 0644]
src/lib/elm_flipselector.c [new file with mode: 0644]
src/lib/elm_font.c [new file with mode: 0644]
src/lib/elm_frame.c [new file with mode: 0644]
src/lib/elm_gengrid.c [new file with mode: 0644]
src/lib/elm_genlist.c [new file with mode: 0644]
src/lib/elm_hover.c [new file with mode: 0644]
src/lib/elm_icon.c [new file with mode: 0644]
src/lib/elm_image.c [new file with mode: 0644]
src/lib/elm_index.c [new file with mode: 0644]
src/lib/elm_label.c [new file with mode: 0644]
src/lib/elm_layout.c [new file with mode: 0644]
src/lib/elm_list.c [new file with mode: 0644]
src/lib/elm_main.c [new file with mode: 0644]
src/lib/elm_map.c [new file with mode: 0644]
src/lib/elm_mapbuf.c [new file with mode: 0644]
src/lib/elm_menu.c [new file with mode: 0644]
src/lib/elm_module.c [new file with mode: 0644]
src/lib/elm_notify.c [new file with mode: 0644]
src/lib/elm_pager.c [new file with mode: 0644]
src/lib/elm_panel.c [new file with mode: 0644]
src/lib/elm_panes.c [new file with mode: 0644]
src/lib/elm_photo.c [new file with mode: 0644]
src/lib/elm_photocam.c [new file with mode: 0644]
src/lib/elm_priv.h [new file with mode: 0644]
src/lib/elm_progressbar.c [new file with mode: 0644]
src/lib/elm_radio.c [new file with mode: 0644]
src/lib/elm_scroller.c [new file with mode: 0644]
src/lib/elm_separator.c [new file with mode: 0644]
src/lib/elm_slider.c [new file with mode: 0644]
src/lib/elm_slideshow.c [new file with mode: 0644]
src/lib/elm_spinner.c [new file with mode: 0644]
src/lib/elm_store.c [new file with mode: 0644]
src/lib/elm_table.c [new file with mode: 0644]
src/lib/elm_theme.c [new file with mode: 0644]
src/lib/elm_thumb.c [new file with mode: 0644]
src/lib/elm_toggle.c [new file with mode: 0644]
src/lib/elm_toolbar.c [new file with mode: 0644]
src/lib/elm_transit.c [new file with mode: 0644]
src/lib/elm_util.c [new file with mode: 0644]
src/lib/elm_widget.c [new file with mode: 0644]
src/lib/elm_widget.h [new file with mode: 0644]
src/lib/elm_win.c [new file with mode: 0644]
src/lib/els_box.c [new file with mode: 0644]
src/lib/els_box.h [new file with mode: 0644]
src/lib/els_cursor.c [new file with mode: 0644]
src/lib/els_icon.c [new file with mode: 0644]
src/lib/els_icon.h [new file with mode: 0644]
src/lib/els_pan.c [new file with mode: 0644]
src/lib/els_pan.h [new file with mode: 0644]
src/lib/els_scroller.c [new file with mode: 0644]
src/lib/els_scroller.h [new file with mode: 0644]
src/lib/els_tooltip.c [new file with mode: 0644]
src/modules/Makefile.am [new file with mode: 0644]
src/modules/test_entry/Makefile.am [new file with mode: 0644]
src/modules/test_entry/mod.c [new file with mode: 0644]
src/modules/test_map/Makefile.am [new file with mode: 0644]
src/modules/test_map/mod.c [new file with mode: 0644]
tests/test_decl.sh [new file with mode: 0755]
tests/test_eapi.sh [new file with mode: 0755]
tests/test_getter.sh [new file with mode: 0755]
tests/test_setter.sh [new file with mode: 0755]
tests/test_setter_blacklist.txt [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..dcdce19
--- /dev/null
@@ -0,0 +1,43 @@
+*.lo
+*.o
+*.la
+.libs
+.deps
+.*.swp
+*.pc
+Makefile
+Makefile.in
+*.so
+*.edj
+elementary_config
+elementary_quicklaunch
+elementary_run
+elementary_test
+elementary_testql
+/aclocal.m4
+/autom4te.cache/
+/config.guess
+/config.log
+/config.status
+/config.sub
+/configure
+/depcomp
+/elementary.spec
+/elementary_config.h
+/elementary_config.h.in
+/install-sh
+/libtool
+/ltmain.sh
+/missing
+/stamp-h1
+core
+cscope.out
+doc/elementary.dox
+elementary.spec
+m4/libtool.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
+src/lib/Elementary.h
+tags
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..52c3367
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,36 @@
+The Rasterman (Carsten Haitzler) <raster@rasterman.com>
+Gustavo Sverzut Barbieri <barbieri@profusion.mobi>
+Cedric Bail <cedric.bail@free.fr>
+Vincent Torri <vtorri@univ-evry.fr>
+Daniel Kolesa <quaker66@gmail.com>
+Jaime Thomas <avi.thomas@gmail.com>
+Swisscom - http://www.swisscom.ch/
+Christopher Michael <devilhorns@comcast.net>
+Marco Trevisan (Treviño) <mail@3v1n0.net>
+Michael Bouchaud <michael.bouchaud@gmail.com>
+Jonathan Atton (Watchwolf) <jonathan.atton@gmail.com>
+Brian Wang <brian.wang.0721@gmail.com>
+Mike Blumenkrantz (zmike) <mike@zentific.com>
+Samsung Electronics <tbd>
+Samsung SAIT <tbd>
+Brett Nash <nash@nash.id.au>
+Bruno Dilly <bdilly@profusion.mobi>
+Rafael Fonseca <rfonseca@profusion.mobi>
+Hermet (Chuneon Park) <chuneon.park@samsung.com>
+Woohyun Jung <wh0705.jung@samsung.com>
+Jaehwan Kim <jae.hwan.kim@samsung.com>
+Wonguk Jeong <wonguk.jeong@samsung.com>
+Leandro A. F. Pereira <leandro@profusion.mobi>
+Helen Fornazier <helen.fornazier@profusion.mobi>
+Gustavo Lima Chaves <glima@profusion.mobi>
+Fabiano Fidêncio <fidencio@profusion.mobi>
+Tiago Falcão <tiago@profusion.mobi>
+Otavio Pontes <otavio@profusion.mobi>
+Viktor Kojouharov <vkojouharov@gmail.com>
+Daniel Juyung Seo (SeoZ) <juyung.seo@samsung.com> <seojuyung2@gmail.com>
+Sangho Park <sangho.g.park@samsung.com> <gouache95@gmail.com>
+Rajeev Ranjan (Rajeev) <rajeev.r@samsung.com> <rajeev.jnnce@gmail.com>
+Seunggyun Kim <sgyun.kim@samsung.com> <tmdrbs@gmail.com>
+Sohyun Kim <anna1014.kim@samsung.com> <sohyun.anna@gmail.com>
+Jihoon Kim <jihoon48.kim@samsung.com>
+Jeonghyun Yun (arosis) <jh0506.yun@samsung.com>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..ba77514
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,491 @@
+Copyright notice for Elementary:
+
+Copyright (C) 2008-2010 Carsten Haitzler and various contributors (see AUTHORS)
+
+This library is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License.
+
+This library is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+details.
+
+Below is a copy of the GNU Lesser General Public License that is distributed
+along with this library. If you do not have a copy below, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
+02110-1301  USA
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent modules,
+and to copy and distribute the resulting executable under terms of your
+choice, provided that you also meet, for each linked independent module,
+the terms and conditions of the license of that module. An independent
+module is a module which is not derived from or based on this library.
+If you modify this library, you may extend this exception to your version
+of the library, but you are not obliged to do so. If you do not wish to
+do so, delete this exception statement from your version.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..7c9d317
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,14 @@
+COMPILING and INSTALLING:
+
+If you got a official release tar archive do:
+    ./configure
+    
+( otherwise if you got this from enlightenment cvs do: ./autogen.sh )
+    
+Then to compile:
+    make
+
+To install (run this as root, or the user who handles installs):
+    make install
+
+NOTE: You MUST make install Elementary for it to run properly.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..f41c83e
--- /dev/null
@@ -0,0 +1,45 @@
+SUBDIRS = src data config doc
+
+ACLOCAL_AMFLAGS = -I m4
+
+MAINTAINERCLEANFILES = \
+Makefile.in \
+aclocal.m4 \
+config.guess \
+elementary_config.h.in \
+config.sub \
+configure \
+depcomp \
+install-sh \
+ltmain.sh \
+missing \
+$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz \
+$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.bz2 \
+$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc.tar.bz2 \
+m4/libtool.m4 \
+m4/lt~obsolete.m4 \
+m4/ltoptions.m4 \
+m4/ltsugar.m4 \
+m4/ltversion.m4
+
+
+EXTRA_DIST = \
+README \
+AUTHORS \
+COPYING \
+autogen.sh \
+elementary.pc.in \
+elementary.spec \
+elementary.spec.in \
+m4/ac_attribute.m4 \
+m4/efl_binary.m4 \
+m4/efl_doxygen.m4
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = elementary.pc
+
+.PHONY: doc
+
+doc:
+       @echo "entering doc/"
+       $(MAKE) -C doc doc
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..3de8538
--- /dev/null
+++ b/README
@@ -0,0 +1,3 @@
+Elementary - a basic widget set that is easy to use based on EFL for mobile
+touch-screen devices.
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..995ff2f
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f aclocal.m4 ltmain.sh
+
+touch README
+
+echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1
+echo "Running autoheader..." ; autoheader || exit 1
+echo "Running autoconf..." ; autoconf || exit 1
+echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
+echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
+
+if [ -z "$NOCONFIGURE" ]; then
+       ./configure "$@"
+fi
diff --git a/config/Makefile.am b/config/Makefile.am
new file mode 100644 (file)
index 0000000..2fb26b1
--- /dev/null
@@ -0,0 +1,18 @@
+MAINTAINERCLEANFILES = Makefile.in
+SUBDIRS = default standard illume
+
+EET_EET = @eet_eet@
+
+EXTRA_DIST = profile.src
+
+filesdir = $(datadir)/elementary/config
+
+files_DATA = profile.cfg
+
+%.cfg: %.src
+       $(EET_EET) -i \
+       $(top_builddir)/config/$@ config \
+       $< 0
+
+clean-local:
+       rm -rf *.cfg *~
diff --git a/config/default/Makefile.am b/config/default/Makefile.am
new file mode 100644 (file)
index 0000000..ba2bc96
--- /dev/null
@@ -0,0 +1,23 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+EET_EET = @eet_eet@
+
+EXTRA_DIST = \
+        profile.desktop \
+        icon.png \
+       base.src
+
+filesdir = $(datadir)/elementary/config/default
+files_DATA = \
+        profile.desktop \
+        icon.png \
+       base.cfg
+
+%.cfg: %.src
+       $(EET_EET) -e \
+       $(top_builddir)/config/default/$@ config \
+       $< 1
+
+clean-local:
+       rm -rf *.cfg *~
+       
diff --git a/config/default/base.src b/config/default/base.src
new file mode 100644 (file)
index 0000000..5bc2be3
--- /dev/null
@@ -0,0 +1,37 @@
+group "Elm_Config" struct {
+  value "config_version" int: 65539;
+  value "engine" string: "software_x11";
+  value "thumbscroll_enable" uchar: 1;
+  value "thumbscroll_threshold" int: 24;
+  value "thumbscroll_momentum_threshold" double: 100.0;
+  value "thumbscroll_friction" double: 1.0;
+  value "thumbscroll_bounce_friction" double: 0.5;
+  value "thumbscroll_bounce_enable" uchar: 1;
+  value "page_scroll_friction" double: 0.5;
+  value "bring_in_scroll_friction" double: 0.5;
+  value "zoom_friction" double: 0.5;
+  value "thumbscroll_border_friction" double: 0.5;
+  value "scale" double: 1.0;
+  value "bgpixmap" int: 0;
+  value "compositing" int: 1;
+  value "font_hinting" int: 2;
+  value "cache_flush_poll_interval" int: 512;
+  value "cache_flush_enable" uchar: 1;
+  value "image_cache" int: 4096;
+  value "font_cache" int: 512;
+  value "edje_cache" int: 32;
+  value "edje_collection_cache" int: 64;
+  value "finger_size" int: 40;
+  value "fps" double: 60.0;
+  value "theme" string: "default";
+  value "modules" string: "";
+  value "tooltip_delay" double: 1.0;
+  value "cursor_engine_only" uchar: 1;
+  value "focus_highlight_enable" uchar: 0;
+  value "focus_highlight_animate" uchar: 0;
+  value "toolbar_shrink_mode" int: 3;
+  value "fileselector_expand_enable" uchar: 0;
+  value "inwin_dialogs_enable" uchar: 1;
+  value "icon_size" int: 32;
+  value "longpress_timeout" double: 1.0;
+}
diff --git a/config/default/icon.png b/config/default/icon.png
new file mode 100644 (file)
index 0000000..9c08ee2
Binary files /dev/null and b/config/default/icon.png differ
diff --git a/config/default/profile.desktop b/config/default/profile.desktop
new file mode 100644 (file)
index 0000000..3cdfb82
--- /dev/null
@@ -0,0 +1,21 @@
+[Desktop Entry]
+Type=Link
+Name=Default
+Name[cs]=Výchozí
+Name[it]=Predefinito
+Name[hu]=Alapértelmezett
+Name[fr]=Prédéfini
+Name[el]=Προκαθορισμένο
+Name[eo]=Pravaloroj
+Name[zh_CN]=默认
+Namr[pt]=Omissões
+Icon=icon.png
+Comment=Select this to begin<br>the initial setup again.
+Comment[cs]=Vyberte pro znovuspuštění<br>tohoto průvodce.
+Comment[it]=Selezionare questo per riprendere<br>la configurazione iniziale.
+Comment[hu]=Válaszd ezt az alap<br>beállítáok megismétléséhez.
+Comment[fr]=Sélectionnez ceci pour retrouver la<br>configuration par défaut et<br>reprendre le paramétrage<br>initial.
+Comment[el]=Επέλεξε αυτό για να <br>ξεκινήσεις την αρχική ρύθμιση ξανά.
+Comment[eo]=Elektu tion por restartigi<br>la pravalorizan agordon.
+Comment[zh_CN]=点击这里重新进行初始化设置主题。
+Comment[pt]=Selecione isto para executar novamente a configuração inicial
diff --git a/config/illume/Makefile.am b/config/illume/Makefile.am
new file mode 100644 (file)
index 0000000..9aa769d
--- /dev/null
@@ -0,0 +1,22 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+EET_EET = @eet_eet@
+
+EXTRA_DIST = \
+        profile.desktop \
+        icon.png \
+       base.src
+
+filesdir = $(datadir)/elementary/config/illume
+files_DATA = \
+        profile.desktop \
+        icon.png \
+       base.cfg
+
+%.cfg: %.src
+       $(EET_EET) -e \
+       $(top_builddir)/config/illume/$@ config \
+       $< 1
+
+clean-local:
+       rm -rf *.cfg *~
diff --git a/config/illume/base.src b/config/illume/base.src
new file mode 100644 (file)
index 0000000..5bc2be3
--- /dev/null
@@ -0,0 +1,37 @@
+group "Elm_Config" struct {
+  value "config_version" int: 65539;
+  value "engine" string: "software_x11";
+  value "thumbscroll_enable" uchar: 1;
+  value "thumbscroll_threshold" int: 24;
+  value "thumbscroll_momentum_threshold" double: 100.0;
+  value "thumbscroll_friction" double: 1.0;
+  value "thumbscroll_bounce_friction" double: 0.5;
+  value "thumbscroll_bounce_enable" uchar: 1;
+  value "page_scroll_friction" double: 0.5;
+  value "bring_in_scroll_friction" double: 0.5;
+  value "zoom_friction" double: 0.5;
+  value "thumbscroll_border_friction" double: 0.5;
+  value "scale" double: 1.0;
+  value "bgpixmap" int: 0;
+  value "compositing" int: 1;
+  value "font_hinting" int: 2;
+  value "cache_flush_poll_interval" int: 512;
+  value "cache_flush_enable" uchar: 1;
+  value "image_cache" int: 4096;
+  value "font_cache" int: 512;
+  value "edje_cache" int: 32;
+  value "edje_collection_cache" int: 64;
+  value "finger_size" int: 40;
+  value "fps" double: 60.0;
+  value "theme" string: "default";
+  value "modules" string: "";
+  value "tooltip_delay" double: 1.0;
+  value "cursor_engine_only" uchar: 1;
+  value "focus_highlight_enable" uchar: 0;
+  value "focus_highlight_animate" uchar: 0;
+  value "toolbar_shrink_mode" int: 3;
+  value "fileselector_expand_enable" uchar: 0;
+  value "inwin_dialogs_enable" uchar: 1;
+  value "icon_size" int: 32;
+  value "longpress_timeout" double: 1.0;
+}
diff --git a/config/illume/icon.png b/config/illume/icon.png
new file mode 100644 (file)
index 0000000..9e0ed3d
Binary files /dev/null and b/config/illume/icon.png differ
diff --git a/config/illume/profile.desktop b/config/illume/profile.desktop
new file mode 100644 (file)
index 0000000..8619043
--- /dev/null
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Type=Link
+Name=Illume
+Name[el]=Illume
+Name[eo]=Illume
+Name[zh_CN]=Illume
+Icon=icon.png
+Comment=Illume profile for<br>embedded systems like<br>phones and web<br>tablets with tiny<br>touchscreen displays.<br>Only use this if<br>you really have<br>such a device.
+Comment[cs]=Illume profil pro<br>přenosná zařízení<br>jako telefony<br>a webové tablety<br>s malými dotykovými displeji.<br>Použijte jen pokud<br>opravdu máte<br>takové zařízení.
+Comment[it]=Profilo Illume per sistemi embedded come<br>cellulari e webpad con piccoli display<br>touchscreen. Usatelo solo se<br>avete realmente un dispositivo simile.
+Comment[hu]=Illume profil <br>telefonokhoz, érintőképernyőkhöz.<br>Csak akkor használd ezt,<br>ha valóban ilyen eszközöd van.
+Comment[fr]=Profil Illume pour les systèmes embarqués<br>comme les téléphones et les tablettes<br>Internet pourvus d'un petit écran<br>tactile. À n'utiliser que si vous<br>disposez d'un tel matériel.
+Comment[el]=Το προφίλ Illume είναι<br>για μικροσυσκευές όπως <br>κινητά τηλέφωνα ή internet<br>tablets με μικρές οθόνες αφής.<br>Επιλέξτε μόνο αν έχετε τέτοια<br>συσκευή.
+Comment[eo]=Profilo Illume por la<br>enkorpigitaj sistemoj<br>kiel la telefonoj kaj<br>ttt-tabletoj kun etaj<br>tuŝekranoj. Nur uzu<br>tiun se vi vere havas<br>tian aparaton.
+Comment[zh_CN]=为带有小型触屏的嵌入式系统如手机和上网本设计的 Illume 设置主题。
+Comment[pt]=Perfil para telemóveis e web tablets com pequenos ecrãs tácteis.<br>Só deve ser utilizado para dispositivos deste tipo
diff --git a/config/profile.src b/config/profile.src
new file mode 100644 (file)
index 0000000..331d858
--- /dev/null
@@ -0,0 +1 @@
+default
\ No newline at end of file
diff --git a/config/standard/Makefile.am b/config/standard/Makefile.am
new file mode 100644 (file)
index 0000000..88cae80
--- /dev/null
@@ -0,0 +1,23 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+EET_EET = @eet_eet@
+
+EXTRA_DIST = \
+        profile.desktop \
+        icon.png \
+       base.src
+
+filesdir = $(datadir)/elementary/config/standard
+files_DATA = \
+        profile.desktop \
+        icon.png \
+       base.cfg
+
+%.cfg: %.src
+       $(EET_EET) -e \
+       $(top_builddir)/config/standard/$@ config \
+       $< 1
+
+clean-local:
+       rm -rf *.cfg *~
+       
diff --git a/config/standard/base.src b/config/standard/base.src
new file mode 100644 (file)
index 0000000..142e0e7
--- /dev/null
@@ -0,0 +1,37 @@
+group "Elm_Config" struct {
+  value "config_version" int: 65539;
+  value "engine" string: "software_x11";
+  value "thumbscroll_enable" uchar: 0;
+  value "thumbscroll_threshold" int: 4;
+  value "thumbscroll_momentum_threshold" double: 100.0;
+  value "thumbscroll_friction" double: 1.0;
+  value "thumbscroll_bounce_friction" double: 0.5;
+  value "thumbscroll_bounce_enable" uchar: 0;
+  value "page_scroll_friction" double: 0.5;
+  value "bring_in_scroll_friction" double: 0.5;
+  value "zoom_friction" double: 0.5;
+  value "thumbscroll_border_friction" double: 0.5;
+  value "scale" double: 1.0;
+  value "bgpixmap" int: 0;
+  value "compositing" int: 1;
+  value "font_hinting" int: 2;
+  value "cache_flush_poll_interval" int: 512;
+  value "cache_flush_enable" uchar: 1;
+  value "image_cache" int: 4096;
+  value "font_cache" int: 512;
+  value "edje_cache" int: 32;
+  value "edje_collection_cache" int: 64;
+  value "finger_size" int: 5;
+  value "fps" double: 60.0;
+  value "theme" string: "default-desktop";
+  value "modules" string: "";
+  value "tooltip_delay" double: 1.0;
+  value "cursor_engine_only" uchar: 1;
+  value "focus_highlight_enable" uchar: 0;
+  value "focus_highlight_animate" uchar: 0;
+  value "toolbar_shrink_mode" int: 3;
+  value "fileselector_expand_enable" uchar: 1;
+  value "inwin_dialogs_enable" uchar: 0;
+  value "icon_size" int: 32;
+  value "longpress_timeout" double: 1.0;
+}
diff --git a/config/standard/icon.png b/config/standard/icon.png
new file mode 100644 (file)
index 0000000..90b57af
Binary files /dev/null and b/config/standard/icon.png differ
diff --git a/config/standard/profile.desktop b/config/standard/profile.desktop
new file mode 100644 (file)
index 0000000..3542a56
--- /dev/null
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Type=Link
+Name=Standard
+Name[cs]=Standartní
+Name[hu]=Általános
+Name[el]=Κανονικό
+Name[eo]=Kutima
+Name[zh_CN]=标准
+Name[pt]=Padrão
+Icon=icon.png
+Comment=This is the standard<br>profile that is<br>universal for most<br>desktop and laptop<br>systems. Choose this<br>if you are not<br>sure what to choose.
+Comment[cs]=Toto je standartní<br>univerzální<br>profil pro většinu<br>stolních a přenosných<br>počítačů. Vyberte pokud<br>si nejste jisti<br>co vybrat.
+Comment[it]=Questo è il profilo standard, universale per la<br>maggior parte dei sistemi desktop e portatili.<br>Scegliete questo se non siete sicuri di cosa scegliere.
+Comment[hu]=Ez az általános,<br>alap beállítás,<br>amely megfelelő a<br>legtöbb laptop és<br>asztali gép számára.
+Comment[fr]=Le profil standard adapté à la quasi totalité<br>des systèmes de bureau et ordinateurs<br>portables. Choisissez ce profil si<br>vous êtes indécis.
+Comment[el]=Αυτό είναι το κανονικό <br>προφίλ που είναι κοινό<br>για τα περισσότερα συστήματα. Επιλέξτε αυτό<br>αν δεν είστε σίγουροι για <br>την επιλογή σας.
+Comment[eo]=Tio estas la kutima profilo<br>taŭga por preskaŭ ĉiuj<br>oficejaj sistemoj kaj<br>porteblaj sistemoj.<br>Elektu ĝin se vi ne certas.
+Comment[zh_CN]=适用于大多数台式机和笔记本的设置主题,如果您不清楚如何选择则请使用这个。
+Comment[pt]=O perfil de configuração padrãoo utilizado para a maioria dos computadores e portáteis.<br>Escolha-o se não souber o que escolher
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..086d53b
--- /dev/null
@@ -0,0 +1,542 @@
+=-------##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+m4_define([v_maj], [0])
+m4_define([v_min], [7])
+m4_define([v_mic], [0])
+m4_define([v_rev], m4_esyscmd([(svnversion "${SVN_REPO_PATH:-.}" | grep -v export || echo 0) | awk -F : '{printf("%s\n", $1);}' | tr -d ' :MSP\n']))
+m4_if(v_rev, [0], [m4_define([v_rev], m4_esyscmd([git log 2> /dev/null | (grep -m1 git-svn-id || echo 0) | sed -e 's/.*@\([0-9]*\).*/\1/' | tr -d '\n']))])
+##--   When released, remove the dnl on the below line
+dnl m4_undefine([v_rev])
+##--   When doing snapshots - change soname. remove dnl on below line
+m4_define([relname], [ver-pre-svn-09])
+m4_define([v_rel], [-release relname])
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+m4_ifdef([v_rev], [m4_define([v_ver], [v_maj.v_min.v_mic.v_rev])],
+[m4_define([v_ver], [v_maj.v_min.v_mic])])
+m4_define([lt_rev], m4_eval(v_maj + v_min))
+m4_define([lt_cur], v_mic)
+m4_define([lt_age], v_min)
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+
+AC_INIT([elementary], [v_ver], [enlightenment-devel@lists.sourceforge.net])
+AC_PREREQ(2.52)
+AC_CONFIG_SRCDIR([configure.ac])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+
+AC_CONFIG_HEADERS([elementary_config.h])
+AH_TOP([
+#ifndef EFL_CONFIG_H__
+#define EFL_CONFIG_H__
+])
+AH_BOTTOM([
+#endif /* EFL_CONFIG_H__ */
+])
+
+AM_INIT_AUTOMAKE([1.6 dist-bzip2])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_GNU_SOURCE
+
+AC_C_BIGENDIAN
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+AC_C_CONST
+AC_C___ATTRIBUTE__
+AC_FUNC_ALLOCA
+
+AC_LIBTOOL_WIN32_DLL
+define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
+define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
+AC_PROG_LIBTOOL
+
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+m4_ifdef([v_rev], , [m4_define([v_rev], [0])])
+m4_ifdef([v_rel], , [m4_define([v_rel], [])])
+AC_DEFINE_UNQUOTED(VMAJ, [v_maj], [Major version])
+AC_DEFINE_UNQUOTED(VMIN, [v_min], [Minor version])
+AC_DEFINE_UNQUOTED(VMIC, [v_mic], [Micro version])
+AC_DEFINE_UNQUOTED(VREV, [v_rev], [Revison])
+version_info="lt_rev:lt_cur:lt_age"
+release_info="v_rel"
+AC_SUBST(version_info)
+AC_SUBST(release_info)
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+VMAJ=v_maj
+VMIN=v_min
+AC_SUBST(VMAJ)
+AC_SUBST(VMIN)
+
+EDJE_VERSION="1.0.0"
+
+case "$host_os" in
+  mingw32ce* | cegcc*)
+    MODULE_ARCH="$host_os-$host_cpu"
+    MODULE_EDJE="$host_os-$host_cpu"
+    ;;
+  *)
+    MODULE_ARCH="$host_os-$host_cpu-v_maj.v_min.v_mic"
+    MODULE_EDJE="$host_os-$host_cpu-${EDJE_VERSION}"
+    ;;
+esac
+AC_SUBST(release_info)
+AC_SUBST(MODULE_ARCH)
+AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture")
+AC_SUBST(MODULE_EDJE)
+AC_DEFINE_UNQUOTED(MODULE_EDJE, "$MODULE_EDJE", "Edje module architecture")
+
+EFL_SHARED_EXTENSION="${shrext_cmds}"
+AC_DEFINE_UNQUOTED(EFL_SHARED_EXTENSION, "${EFL_SHARED_EXTENSION}", "Shared extension")
+
+requirement_elm=""
+
+PKG_PROG_PKG_CONFIG
+
+# Check whether pkg-config supports Requires.private
+if $PKG_CONFIG --atleast-pkgconfig-version 0.22; then
+   pkgconfig_requires_private="Requires.private"
+else
+   pkgconfig_requires_private="Requires"
+fi
+AC_SUBST(pkgconfig_requires_private)
+
+lt_enable_auto_import=""
+ELM_UNIX_DEF="#undef"
+ELM_WIN32_DEF="#undef"
+ELM_WINCE_DEF="#undef"
+have_windows="no"
+case "$host_os" in
+   mingw32ce* | cegcc*)
+      PKG_CHECK_MODULES([EVIL], [evil])
+      AC_DEFINE(HAVE_EVIL, 1, [Set to 1 if evil package is installed.])
+      lt_enable_auto_import="-Wl,--enable-auto-import"
+      ELM_WINCE_DEF="#define"
+      have_windows="yes"
+dnl managed by evil
+      AC_DEFINE(HAVE_DLADDR)
+      dlopen_libs=-ldl
+      requirement_elm="evil"
+      have_socket="no"
+    ;;
+   mingw*)
+      PKG_CHECK_MODULES([EVIL], [evil])
+      AC_DEFINE(HAVE_EVIL, 1, [Set to 1 if evil package is installed.])
+      lt_enable_auto_import="-Wl,--enable-auto-import"
+      ELM_WIN32_DEF="#define"
+      have_windows="yes"
+dnl managed by evil
+      AC_DEFINE(HAVE_DLADDR)
+      dlopen_libs=-ldl
+      requirement_elm="evil"
+      have_socket="no"
+      ;;
+   *solaris*)
+      ELM_UNIX_DEF="#define"
+      have_socket="yes"
+      AC_CHECK_LIB([socket], [connect], [], [have_socket="no"])
+      ;;
+   darwin*)
+      ELM_UNIX_DEF="#define"
+      have_socket="yes"
+      AC_CHECK_HEADERS([crt_externs.h])
+      AC_DEFINE([environ], [(*_NSGetEnviron())], ["apple doesn't follow POSIX in this case."])
+      ;;
+   *)
+      ELM_UNIX_DEF="#define"
+      AC_CHECK_FUNCS(dlopen, res=yes, res=no)
+      if test "x$res" = "xyes"; then
+       AC_CHECK_FUNCS(dladdr, AC_DEFINE(HAVE_DLADDR))
+      else
+       AC_CHECK_LIB(dl, dlopen, res=yes, res=no)
+       if test "x$res" = "xyes"; then
+         AC_CHECK_LIB(dl, dladdr, AC_DEFINE(HAVE_DLADDR))
+         dlopen_libs=-ldl
+       else
+         AC_MSG_ERROR(Cannot find dlopen)
+       fi
+      fi
+      have_socket="yes"
+      ;;
+esac
+AM_CONDITIONAL([BUILD_RUN], [test "x$have_socket" = "xyes"])
+
+have_fork="no"
+want_quicklaunch="auto"
+AC_ARG_ENABLE([quick-launch],
+       [AC_HELP_STRING([--disable-quick-launch], [disable quick-launch support, @<:@default=detect@:>@])],
+       [want_quicklaunch=$enableval], [])
+
+if test "x$want_quicklaunch" != "xno"; then
+   AC_CHECK_FUNCS(fork, [
+       have_fork="yes"
+       AC_DEFINE(HAVE_FORK)
+   ])
+fi
+AM_CONDITIONAL([BUILD_QUICKLAUNCH], [test "x$have_fork" = "xyes"])
+
+AC_SUBST(dlopen_libs)
+AC_SUBST(lt_enable_auto_import)
+AC_SUBST(ELM_UNIX_DEF)
+AC_SUBST(ELM_WIN32_DEF)
+AC_SUBST(ELM_WINCE_DEF)
+
+AM_CONDITIONAL([ELEMENTARY_WINDOWS_BUILD], [test "x${have_windows}" = "xyes"])
+
+PKG_CHECK_MODULES([ELEMENTARY],
+   [
+    eina >= 1.0.0
+    eet >= 1.4.0
+    evas >= 1.0.0
+    ecore >= 1.0.0
+    ecore-evas >= 1.0.0
+    ecore-file >= 1.0.0
+    ecore-imf >= 1.0.0
+    edje >= ${EDJE_VERSION}
+   ]
+)
+
+requirement_elm="edje >= ${EDJE_VERSION} ecore-file >= 1.0.0 ecore-evas >= 1.0.0 ecore >= 1.0.0 evas >= 1.0.0 eet >= 1.4.0 eina >= 1.0.0 ${requirement_elm}"
+
+have_elementary_x="no"
+want_elementary_x="auto"
+AC_ARG_ENABLE([ecore-x],
+   [AC_HELP_STRING([--disable-ecore-x], [disable ecore-x support. @<:@default=detect@:>@])],
+   [want_elementary_x=$enableval], [])
+
+if test "x$want_elementary_x" != "xno"; then
+   PKG_CHECK_MODULES([ELEMENTARY_X],
+      [ecore-x >= 1.0.0],
+      [
+       AC_DEFINE(HAVE_ELEMENTARY_X, 1, [X11 support for Elementary])
+       have_elementary_x="yes"
+       requirement_elm="ecore-x >= 1.0.0 ${requirement_elm}"
+      ],
+      [have_elementary_x="no"]
+   )
+else
+    have_elementary_x="no"
+fi
+if test "x$want_elementary_x" = "xyes" -a "x$have_elementary_x" = "xno"; then
+    AC_MSG_ERROR([ecore-x support requested, but not found by pkg-config.])
+fi
+
+
+have_elementary_fb="no"
+want_elementary_fb="auto"
+AC_ARG_ENABLE([ecore-fb],
+   [AC_HELP_STRING([--disable-ecore-fb], [disable ecore-fb support. @<:@default=detect@:>@])],
+   [want_elementary_fb=$enableval], [])
+
+if test "x$want_elementary_fb" != "xno"; then
+   PKG_CHECK_MODULES([ELEMENTARY_FB],
+      [ecore-fb >= 1.0.0],
+      [
+       AC_DEFINE(HAVE_ELEMENTARY_FB, 1, [FB support for Elementary])
+       have_elementary_fb="yes"
+       requirement_elm="ecore-fb >= 1.0.0 ${requirement_elm}"
+      ],
+      [have_elementary_fb="no"]
+   )
+else
+    have_elementary_fb="no"
+fi
+if test "x$want_elementary_fb" = "xyes" -a "x$have_elementary_fb" = "xno"; then
+    AC_MSG_ERROR([ecore-fb support requested, but not found by pkg-config.])
+fi
+
+have_elementary_sdl="no"
+want_elementary_sdl="auto"
+AC_ARG_ENABLE([ecore-sdl],
+   [AC_HELP_STRING([--disable-ecore-sdl], [disable ecore-sdl support. @<:@default=detect@:>@])],
+   [want_elementary_sdl=$enableval], [])
+
+if test "x$want_elementary_sdl" != "xno"; then
+   PKG_CHECK_MODULES([ELEMENTARY_SDL],
+      [ecore-sdl >= 1.0.0],
+      [
+       AC_DEFINE(HAVE_ELEMENTARY_SDL, 1, [SDL support for Elementary])
+       have_elementary_sdl="yes"
+       requirement_elm="ecore-sdl >= 1.0.0 ${requirement_elm}"
+      ],
+      [have_elementary_sdl="no"]
+   )
+else
+    have_elementary_sdl="no"
+fi
+if test "x$want_elementary_sdl" = "xyes" -a "x$have_elementary_sdl" = "xno"; then
+    AC_MSG_ERROR([ecore-sdl support requested, but not found by pkg-config.])
+fi
+
+have_elementary_win32="no"
+want_elementary_win32="auto"
+AC_ARG_ENABLE([ecore-win32],
+   [AC_HELP_STRING([--disable-ecore-win32], [disable ecore-win32 support. @<:@default=detect@:>@])],
+   [want_elementary_win32=$enableval], [])
+
+if test "x$want_elementary_win32" != "xno"; then
+   PKG_CHECK_MODULES([ELEMENTARY_WIN32],
+      [ecore-win32 >= 1.0.0],
+      [
+       AC_DEFINE(HAVE_ELEMENTARY_WIN32, 1, [Windows XP support for Elementary])
+       have_elementary_win32="yes"
+       requirement_elm="ecore-win32 >= 1.0.0 ${requirement_elm}"
+      ],
+      [have_elementary_win32="no"]
+   )
+else
+    have_elementary_win32="no"
+fi
+if test "x$want_elementary_win32" = "xyes" -a "x$have_elementary_win32" = "xno"; then
+    AC_MSG_ERROR([ecore-win32 support requested, but not found by pkg-config.])
+fi
+
+have_elementary_wince="no"
+want_elementary_wince="auto"
+AC_ARG_ENABLE([ecore-wince],
+   [AC_HELP_STRING([--disable-ecore-wince], [disable ecore-wince support. @<:@default=detect@:>@])],
+   [want_elementary_wince=$enableval], [])
+
+if test "x$want_elementary_wince" != "xno"; then
+   PKG_CHECK_MODULES([ELEMENTARY_WINCE],
+      [ecore-wince >= 1.0.0],
+      [
+       AC_DEFINE(HAVE_ELEMENTARY_WINCE, 1, [Windows CE support for Elementary])
+       have_elementary_wince="yes"
+       requirement_elm="ecore-wince >= 1.0.0 ${requirement_elm}"
+      ],
+      [have_elementary_wince="no"]
+   )
+else
+    have_elementary_wince="no"
+fi
+if test "x$want_elementary_wince" = "xyes" -a "x$have_elementary_wince" = "xno"; then
+    AC_MSG_ERROR([ecore-wince support requested, but not found by pkg-config.])
+fi
+
+ELM_EDBUS_DEF="#undef"
+have_elementary_edbus="no"
+want_elementary_edbus="auto"
+AC_ARG_ENABLE([edbus],
+   [AC_HELP_STRING([--disable-edbus], [disable edbus support. @<:@default=detect@:>@])],
+   [want_elementary_edbus=$enableval], [])
+
+if test "x$want_elementary_edbus" != "xno"; then
+    PKG_CHECK_MODULES([ELEMENTARY_EDBUS],
+       [
+        edbus >= 1.0.0
+       ],
+       [
+        AC_DEFINE(HAVE_ELEMENTARY_EDBUS, 1, [EDBus support for Elementary])
+        have_elementary_edbus="yes"
+        ELM_EDBUS_DEF="#define"
+        requirement_elm="edbus >= 1.0.0 ${requirement_elm}"
+       ],
+       [have_elementary_edbus="no"]
+    )
+else
+    have_elementary_edbus="no"
+fi
+if test "x$want_elementary_edbus" = "xyes" -a "x$have_elementary_edbus" = "xno"; then
+    AC_MSG_ERROR([E_DBus support requested, but no e_dbus found by pkg-config.])
+fi
+AC_SUBST(ELM_EDBUS_DEF)
+
+ELM_EFREET_DEF="#undef"
+have_elementary_efreet="no"
+want_elementary_efreet="auto"
+AC_ARG_ENABLE([efreet],
+   [AC_HELP_STRING([--disable-efreet], [disable efreet support. @<:@default=detect@:>@])],
+   [want_elementary_efreet=$enableval], [])
+
+if test "x$want_elementary_efreet" != "xno"; then
+    PKG_CHECK_MODULES([ELEMENTARY_EFREET],
+       [
+        efreet >= 1.0.0
+        efreet-mime >= 1.0.0
+        efreet-trash >= 1.0.0
+       ],
+       [
+        AC_DEFINE(HAVE_ELEMENTARY_EFREET, 1, [Efreet support for Elementary])
+        have_elementary_efreet="yes"
+        ELM_EFREET_DEF="#define"
+        requirement_elm="efreet >= 1.0.0 efreet-mime >= 1.0.0 efreet-trash >= 1.0.0 ${requirement_elm}"
+       ],
+       [have_elementary_efreet="no"]
+    )
+else
+    have_elementary_efreet="no"
+fi
+if test "x$want_elementary_efreet" = "xyes" -a "x$have_elementary_efreet" = "xno"; then
+    AC_MSG_ERROR([Efreet support requested, but no efreet/efreet-mime/efreet-trash found by pkg-config.])
+fi
+AC_SUBST(ELM_EFREET_DEF)
+
+ELM_EWEATHER_DEF="#undef"
+have_elementary_eweather="no"
+want_elementary_eweather="auto"
+AC_ARG_ENABLE([eweather],
+   [AC_HELP_STRING([--disable-eweather], [disable eweather support. @<:@default=detect@:>@])],
+   [want_elementary_eweather=$enableval], [])
+
+if test "x$want_elementary_eweather" != "xno"; then
+    PKG_CHECK_MODULES([ELEMENTARY_EWEATHER],
+       [
+        eweather
+       ],
+       [
+        AC_DEFINE(HAVE_ELEMENTARY_EWEATHER, 1, [EWeather support for Elementary])
+        have_elementary_eweather="yes"
+        ELM_EWEATHER_DEF="#define"
+        requirement_elm="eweather ${requirement_elm}"
+       ],
+       [have_elementary_eweather="no"]
+    )
+else
+    have_elementary_eweather="no"
+fi
+if test "x$want_elementary_eweather" = "xyes" -a "x$have_elementary_eweather" = "xno"; then
+    AC_MSG_ERROR([Eweather support requested, but no eweather found by pkg-config.])
+fi
+AC_SUBST(ELM_EWEATHER_DEF)
+
+ELM_ETHUMB_DEF="#undef"
+have_elementary_ethumb="no"
+want_elementary_ethumb="auto"
+AC_ARG_ENABLE([ethumb],
+   [AC_HELP_STRING([--disable-ethumb], [disable ethumb support. @<:@default=detect@:>@])],
+   [want_elementary_ethumb=$enableval], [])
+
+if test "x$want_elementary_ethumb" != "xno"; then
+    PKG_CHECK_MODULES([ELEMENTARY_ETHUMB],
+       [
+        ethumb_client
+       ],
+       [
+        AC_DEFINE(HAVE_ELEMENTARY_ETHUMB, 1, [Ethumb support for Elementary])
+        have_elementary_ethumb="yes"
+        ELM_ETHUMB_DEF="#define"
+        requirement_elm="ethumb_client ${requirement_elm}"
+       ],
+       [have_elementary_ethumb="no"]
+    )
+else
+    have_elementary_ethumb="no"
+fi
+if test "x$want_elementary_ethumb" = "xyes" -a "x$have_elementary_ethumb" = "xno"; then
+    AC_MSG_ERROR([Ethumb support requested, but no ethumb found by pkg-config.])
+fi
+AC_SUBST(ELM_ETHUMB_DEF)
+
+ELM_DEBUG_DEF="#undef"
+want_elementary_debug="no"
+AC_ARG_ENABLE([debug],
+   [AC_HELP_STRING([--enable-debug], [enable elementary debug support. @<:@default=disabled@:>@])],
+   [want_elementary_debug=$enableval], [])
+
+if test "x$want_elementary_debug" = "xyes"; then
+        AC_DEFINE(HAVE_ELEMENTARY_DEBUG, 1, [Elementary debug.])
+        ELM_DEBUG_DEF="#define"
+fi
+AC_SUBST(ELM_DEBUG_DEF)
+
+ELM_ALLOCA_H_DEF="#undef"
+AC_CHECK_HEADER(alloca.h, [ELM_ALLOCA_H_DEF="#define"])
+AC_SUBST(ELM_ALLOCA_H_DEF)
+
+ELM_LIBINTL_H_DEF="#undef"
+AC_CHECK_HEADER(libintl.h, [ELM_LIBINTL_H_DEF="#define"])
+AC_SUBST(ELM_LIBINTL_H_DEF)
+
+EFL_CHECK_THREADS([
+  TH=1
+] , [
+  AC_MSG_ERROR(no thread support found. required.)
+  exit 1
+])
+AC_SUBST(EFL_PTHREAD_CFLAGS)
+AC_SUBST(EFL_PTHREAD_LIBS)
+
+my_libs="-lm"
+AC_SUBST(my_libs)
+AC_SUBST(requirement_elm)
+
+EFL_WITH_BIN([eet], [eet-eet], [eet])
+EFL_WITH_BIN([edje], [edje-cc], [edje_cc])
+
+EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"])
+
+EFL_ENABLE_BIN([elementary-test])
+EFL_ENABLE_BIN([elementary-config])
+
+AC_OUTPUT([
+Makefile
+elementary.spec
+elementary.pc
+doc/elementary.dox
+doc/Makefile
+src/Makefile
+src/lib/Makefile
+src/lib/Elementary.h
+src/bin/Makefile
+src/modules/Makefile
+src/modules/test_entry/Makefile
+src/modules/test_map/Makefile
+src/edje_externals/Makefile
+data/Makefile
+data/themes/Makefile
+data/images/Makefile
+data/objects/Makefile
+data/desktop/Makefile
+data/edje_externals/Makefile
+config/Makefile
+config/default/Makefile
+config/standard/Makefile
+config/illume/Makefile
+])
+
+#####################################################################
+## Info
+
+echo
+echo
+echo
+echo "------------------------------------------------------------------------"
+echo "$PACKAGE $VERSION"
+echo "------------------------------------------------------------------------"
+echo
+echo "Configuration Options Summary:"
+echo
+echo "  Engines:"
+echo "    X11....................: ${have_elementary_x}"
+echo "    Framebuffer............: ${have_elementary_fb}"
+echo "    SDL....................: ${have_elementary_sdl}"
+echo "    Windows XP.............: ${have_elementary_win32}"
+echo "    Windows CE.............: ${have_elementary_wince}"
+echo
+echo "  Features:"
+echo "    EDBus..................: ${have_elementary_edbus}"
+echo "    EFreet.................: ${have_elementary_efreet}"
+echo "    EWeather...............: ${have_elementary_eweather}"
+echo "    Ethumb.................: ${have_elementary_ethumb}"
+echo "    Quick Launch...........: ${have_fork}"
+echo
+echo "  eet......................: ${eet_eet}"
+echo "  edje_cc..................: ${edje_cc}"
+echo
+echo "  Build elementary_test....: ${have_elementary_test}"
+echo "  Build elementary_config..: ${have_elementary_config}"
+echo
+echo "Compilation................: make (or gmake)"
+echo "  CPPFLAGS.................: $CPPFLAGS"
+echo "  CFLAGS...................: $CFLAGS"
+echo "  LDFLAGS..................: $LDFLAGS"
+echo
+echo "Installation...............: make install (as root if needed, with 'su' or 'sudo')"
+echo "  prefix...................: $prefix"
+echo
diff --git a/data/.cvsignore b/data/.cvsignore
new file mode 100644 (file)
index 0000000..d880450
--- /dev/null
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+default.edj
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644 (file)
index 0000000..17807ed
--- /dev/null
@@ -0,0 +1,3 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+SUBDIRS              = themes images objects desktop edje_externals
diff --git a/data/desktop/Makefile.am b/data/desktop/Makefile.am
new file mode 100644 (file)
index 0000000..14e5d0f
--- /dev/null
@@ -0,0 +1,10 @@
+4AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+desktopdir = $(datadir)/applications
+desktop_DATA = elementary_test.desktop elementary_config.desktop
+
+icondir = $(datadir)/icons
+icon_DATA = elementary.png
+
+EXTRA_DIST = $(desktop_DATA) $(icon_DATA)
diff --git a/data/desktop/elementary.png b/data/desktop/elementary.png
new file mode 100644 (file)
index 0000000..7975489
Binary files /dev/null and b/data/desktop/elementary.png differ
diff --git a/data/desktop/elementary_config.desktop b/data/desktop/elementary_config.desktop
new file mode 100644 (file)
index 0000000..65e326f
--- /dev/null
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Elementary Configuration
+Name[pt]=Configuração do Elementary
+Comment=Elementary Configuration
+Comment[fr]=Configuration pour Elementary
+Comment[it]=Configurazione di Elementary
+Comment[pt]=Configure o Elementary
+Exec=elementary_config
+Icon=elementary
+Terminal=false
+Type=Application
+Categories=System;Settings;
diff --git a/data/desktop/elementary_test.desktop b/data/desktop/elementary_test.desktop
new file mode 100644 (file)
index 0000000..012240b
--- /dev/null
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Elementary Test
+Comment=Elementary Test Application
+Comment[cs]=Testovací aplikace Elementary
+Comment[fr]=Programme de tests pour Elementary
+Comment[it]=Applicazione di test per Elementary
+Comment[pt]=Uma aplicação de teste do Elementary
+Exec=elementary_test
+Icon=elementary
+Terminal=false
+Type=Application
+Categories=Application;Utility;
diff --git a/data/edje_externals/Makefile.am b/data/edje_externals/Makefile.am
new file mode 100644 (file)
index 0000000..d278cbf
--- /dev/null
@@ -0,0 +1,42 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+EDJE_CC = @edje_cc@
+EDJE_FLAGS = -v -id $(top_srcdir)/data/edje_externals -fd $(top_srcdir)/data/edje_externals
+
+filesdir = $(datadir)/elementary/edje_externals
+files_DATA = icons.edj
+
+EXTRA_DIST = \
+icons.edc \
+ico_anchorblock.png \
+ico_anchorview.png \
+ico_bubble.png \
+ico_button.png \
+ico_check.png \
+ico_clock.png \
+ico_fileselector.png \
+ico_fileselector_button.png \
+ico_genlist.png \
+ico_hoversel.png \
+ico_list.png \
+ico_map.png \
+ico_notepad.png \
+ico_photocam.png \
+ico_progressbar.png \
+ico_radio.png \
+ico_scrolled_entry.png \
+ico_slider.png \
+ico_slideshow.png \
+ico_spinner.png \
+ico_thumb.png \
+ico_toggle.png \
+ico_toolbar.png
+
+icons.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/edje_externals/icons.edc \
+       $(top_builddir)/data/edje_externals/icons.edj
+
+clean-local:
+       rm -f *.edj
diff --git a/data/edje_externals/ico_anchorblock.png b/data/edje_externals/ico_anchorblock.png
new file mode 100644 (file)
index 0000000..a62138e
Binary files /dev/null and b/data/edje_externals/ico_anchorblock.png differ
diff --git a/data/edje_externals/ico_anchorview.png b/data/edje_externals/ico_anchorview.png
new file mode 100644 (file)
index 0000000..7615015
Binary files /dev/null and b/data/edje_externals/ico_anchorview.png differ
diff --git a/data/edje_externals/ico_bubble.png b/data/edje_externals/ico_bubble.png
new file mode 100644 (file)
index 0000000..e2df401
Binary files /dev/null and b/data/edje_externals/ico_bubble.png differ
diff --git a/data/edje_externals/ico_button.png b/data/edje_externals/ico_button.png
new file mode 100644 (file)
index 0000000..842a432
Binary files /dev/null and b/data/edje_externals/ico_button.png differ
diff --git a/data/edje_externals/ico_check.png b/data/edje_externals/ico_check.png
new file mode 100644 (file)
index 0000000..2d05343
Binary files /dev/null and b/data/edje_externals/ico_check.png differ
diff --git a/data/edje_externals/ico_clock.png b/data/edje_externals/ico_clock.png
new file mode 100644 (file)
index 0000000..1a7ed02
Binary files /dev/null and b/data/edje_externals/ico_clock.png differ
diff --git a/data/edje_externals/ico_fileselector.png b/data/edje_externals/ico_fileselector.png
new file mode 100644 (file)
index 0000000..fbf06dc
Binary files /dev/null and b/data/edje_externals/ico_fileselector.png differ
diff --git a/data/edje_externals/ico_fileselector_button.png b/data/edje_externals/ico_fileselector_button.png
new file mode 100644 (file)
index 0000000..6b5c773
Binary files /dev/null and b/data/edje_externals/ico_fileselector_button.png differ
diff --git a/data/edje_externals/ico_genlist.png b/data/edje_externals/ico_genlist.png
new file mode 100644 (file)
index 0000000..ab19494
Binary files /dev/null and b/data/edje_externals/ico_genlist.png differ
diff --git a/data/edje_externals/ico_hoversel.png b/data/edje_externals/ico_hoversel.png
new file mode 100644 (file)
index 0000000..134d12d
Binary files /dev/null and b/data/edje_externals/ico_hoversel.png differ
diff --git a/data/edje_externals/ico_list.png b/data/edje_externals/ico_list.png
new file mode 100755 (executable)
index 0000000..9a1dc64
Binary files /dev/null and b/data/edje_externals/ico_list.png differ
diff --git a/data/edje_externals/ico_map.png b/data/edje_externals/ico_map.png
new file mode 100644 (file)
index 0000000..1c8ca8b
Binary files /dev/null and b/data/edje_externals/ico_map.png differ
diff --git a/data/edje_externals/ico_notepad.png b/data/edje_externals/ico_notepad.png
new file mode 100644 (file)
index 0000000..b957492
Binary files /dev/null and b/data/edje_externals/ico_notepad.png differ
diff --git a/data/edje_externals/ico_photocam.png b/data/edje_externals/ico_photocam.png
new file mode 100644 (file)
index 0000000..c789dbb
Binary files /dev/null and b/data/edje_externals/ico_photocam.png differ
diff --git a/data/edje_externals/ico_progressbar.png b/data/edje_externals/ico_progressbar.png
new file mode 100644 (file)
index 0000000..202aead
Binary files /dev/null and b/data/edje_externals/ico_progressbar.png differ
diff --git a/data/edje_externals/ico_radio.png b/data/edje_externals/ico_radio.png
new file mode 100644 (file)
index 0000000..080f4b0
Binary files /dev/null and b/data/edje_externals/ico_radio.png differ
diff --git a/data/edje_externals/ico_scrolled_entry.png b/data/edje_externals/ico_scrolled_entry.png
new file mode 100644 (file)
index 0000000..443e4c2
Binary files /dev/null and b/data/edje_externals/ico_scrolled_entry.png differ
diff --git a/data/edje_externals/ico_slider.png b/data/edje_externals/ico_slider.png
new file mode 100644 (file)
index 0000000..307f45c
Binary files /dev/null and b/data/edje_externals/ico_slider.png differ
diff --git a/data/edje_externals/ico_slideshow.png b/data/edje_externals/ico_slideshow.png
new file mode 100644 (file)
index 0000000..2341b7a
Binary files /dev/null and b/data/edje_externals/ico_slideshow.png differ
diff --git a/data/edje_externals/ico_spinner.png b/data/edje_externals/ico_spinner.png
new file mode 100644 (file)
index 0000000..0ab2af6
Binary files /dev/null and b/data/edje_externals/ico_spinner.png differ
diff --git a/data/edje_externals/ico_thumb.png b/data/edje_externals/ico_thumb.png
new file mode 100644 (file)
index 0000000..e98ed3d
Binary files /dev/null and b/data/edje_externals/ico_thumb.png differ
diff --git a/data/edje_externals/ico_toggle.png b/data/edje_externals/ico_toggle.png
new file mode 100644 (file)
index 0000000..e22086a
Binary files /dev/null and b/data/edje_externals/ico_toggle.png differ
diff --git a/data/edje_externals/ico_toolbar.png b/data/edje_externals/ico_toolbar.png
new file mode 100644 (file)
index 0000000..c3799cb
Binary files /dev/null and b/data/edje_externals/ico_toolbar.png differ
diff --git a/data/edje_externals/icons.edc b/data/edje_externals/icons.edc
new file mode 100644 (file)
index 0000000..e36ccea
--- /dev/null
@@ -0,0 +1,37 @@
+#define ICON(_name)                                         \
+images { image: "ico_"_name".png" COMP; }                   \
+collections { group { name: "ico_"_name;                    \
+      parts { part { name: "icon";                          \
+            type: IMAGE; mouse_events: 0;                   \
+            description { state: "default" 0.0;             \
+               align: 0.5 0.5;                              \
+               aspect: 1.0 1.0;                             \
+               aspect_preference: VERTICAL;                 \
+               image.normal: "ico_"_name".png";             \
+}}}}}
+
+ICON("anchorblock")
+ICON("anchorview")
+ICON("bubble")
+ICON("button")
+ICON("check")
+ICON("clock")
+ICON("fileselector")
+ICON("fileselector_button")
+ICON("genlist")
+ICON("hoversel")
+ICON("list")
+ICON("map")
+ICON("notepad")
+ICON("photocam")
+ICON("progressbar")
+ICON("radio")
+ICON("scrolled_entry")
+ICON("slider")
+ICON("slideshow")
+ICON("spinner")
+ICON("thumb")
+ICON("toggle")
+ICON("toolbar")
+ICON("slideshow")
+
diff --git a/data/images/Makefile.am b/data/images/Makefile.am
new file mode 100644 (file)
index 0000000..baf9ed5
--- /dev/null
@@ -0,0 +1,47 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+filesdir = $(datadir)/elementary/images
+files_DATA = \
+panel_01.jpg \
+plant_01.jpg \
+rock_01.jpg \
+rock_02.jpg \
+sky_01.jpg \
+sky_02.jpg \
+sky_03.jpg \
+sky_04.jpg \
+wood_01.jpg \
+logo.png \
+logo_small.png \
+parking.png \
+icon_00.png \
+icon_01.png \
+icon_02.png \
+icon_03.png \
+icon_04.png \
+icon_05.png \
+icon_06.png \
+icon_07.png \
+icon_08.png \
+icon_09.png \
+icon_10.png \
+icon_11.png \
+icon_12.png \
+icon_13.png \
+icon_14.png \
+icon_15.png \
+icon_16.png \
+icon_17.png \
+icon_18.png \
+icon_19.png \
+icon_20.png \
+icon_21.png \
+icon_22.png \
+icon_23.png \
+bubble.png \
+bubble_sh.png \
+mystrale.jpg \
+mystrale_2.jpg
+
+EXTRA_DIST = $(files_DATA)
diff --git a/data/images/bubble.png b/data/images/bubble.png
new file mode 100644 (file)
index 0000000..dfb71b7
Binary files /dev/null and b/data/images/bubble.png differ
diff --git a/data/images/bubble_sh.png b/data/images/bubble_sh.png
new file mode 100644 (file)
index 0000000..b66c1e6
Binary files /dev/null and b/data/images/bubble_sh.png differ
diff --git a/data/images/icon_00.png b/data/images/icon_00.png
new file mode 100644 (file)
index 0000000..d026778
Binary files /dev/null and b/data/images/icon_00.png differ
diff --git a/data/images/icon_01.png b/data/images/icon_01.png
new file mode 100644 (file)
index 0000000..faf524c
Binary files /dev/null and b/data/images/icon_01.png differ
diff --git a/data/images/icon_02.png b/data/images/icon_02.png
new file mode 100644 (file)
index 0000000..592cb5a
Binary files /dev/null and b/data/images/icon_02.png differ
diff --git a/data/images/icon_03.png b/data/images/icon_03.png
new file mode 100644 (file)
index 0000000..3d3063b
Binary files /dev/null and b/data/images/icon_03.png differ
diff --git a/data/images/icon_04.png b/data/images/icon_04.png
new file mode 100644 (file)
index 0000000..454bd62
Binary files /dev/null and b/data/images/icon_04.png differ
diff --git a/data/images/icon_05.png b/data/images/icon_05.png
new file mode 100644 (file)
index 0000000..bb81792
Binary files /dev/null and b/data/images/icon_05.png differ
diff --git a/data/images/icon_06.png b/data/images/icon_06.png
new file mode 100644 (file)
index 0000000..7f72520
Binary files /dev/null and b/data/images/icon_06.png differ
diff --git a/data/images/icon_07.png b/data/images/icon_07.png
new file mode 100644 (file)
index 0000000..1c76beb
Binary files /dev/null and b/data/images/icon_07.png differ
diff --git a/data/images/icon_08.png b/data/images/icon_08.png
new file mode 100644 (file)
index 0000000..c8fc8d2
Binary files /dev/null and b/data/images/icon_08.png differ
diff --git a/data/images/icon_09.png b/data/images/icon_09.png
new file mode 100644 (file)
index 0000000..f321617
Binary files /dev/null and b/data/images/icon_09.png differ
diff --git a/data/images/icon_10.png b/data/images/icon_10.png
new file mode 100644 (file)
index 0000000..c72918b
Binary files /dev/null and b/data/images/icon_10.png differ
diff --git a/data/images/icon_11.png b/data/images/icon_11.png
new file mode 100644 (file)
index 0000000..cdb212e
Binary files /dev/null and b/data/images/icon_11.png differ
diff --git a/data/images/icon_12.png b/data/images/icon_12.png
new file mode 100644 (file)
index 0000000..1954b9b
Binary files /dev/null and b/data/images/icon_12.png differ
diff --git a/data/images/icon_13.png b/data/images/icon_13.png
new file mode 100644 (file)
index 0000000..27d964e
Binary files /dev/null and b/data/images/icon_13.png differ
diff --git a/data/images/icon_14.png b/data/images/icon_14.png
new file mode 100644 (file)
index 0000000..2434b05
Binary files /dev/null and b/data/images/icon_14.png differ
diff --git a/data/images/icon_15.png b/data/images/icon_15.png
new file mode 100644 (file)
index 0000000..8ab20ce
Binary files /dev/null and b/data/images/icon_15.png differ
diff --git a/data/images/icon_16.png b/data/images/icon_16.png
new file mode 100644 (file)
index 0000000..7f5ad1e
Binary files /dev/null and b/data/images/icon_16.png differ
diff --git a/data/images/icon_17.png b/data/images/icon_17.png
new file mode 100644 (file)
index 0000000..6afaf7a
Binary files /dev/null and b/data/images/icon_17.png differ
diff --git a/data/images/icon_18.png b/data/images/icon_18.png
new file mode 100644 (file)
index 0000000..74eb0d6
Binary files /dev/null and b/data/images/icon_18.png differ
diff --git a/data/images/icon_19.png b/data/images/icon_19.png
new file mode 100644 (file)
index 0000000..d8784e0
Binary files /dev/null and b/data/images/icon_19.png differ
diff --git a/data/images/icon_20.png b/data/images/icon_20.png
new file mode 100644 (file)
index 0000000..69a9dca
Binary files /dev/null and b/data/images/icon_20.png differ
diff --git a/data/images/icon_21.png b/data/images/icon_21.png
new file mode 100644 (file)
index 0000000..6561e5f
Binary files /dev/null and b/data/images/icon_21.png differ
diff --git a/data/images/icon_22.png b/data/images/icon_22.png
new file mode 100644 (file)
index 0000000..d6130e8
Binary files /dev/null and b/data/images/icon_22.png differ
diff --git a/data/images/icon_23.png b/data/images/icon_23.png
new file mode 100644 (file)
index 0000000..27f5457
Binary files /dev/null and b/data/images/icon_23.png differ
diff --git a/data/images/logo.png b/data/images/logo.png
new file mode 100644 (file)
index 0000000..7dbae67
Binary files /dev/null and b/data/images/logo.png differ
diff --git a/data/images/logo_small.png b/data/images/logo_small.png
new file mode 100644 (file)
index 0000000..c7dc665
Binary files /dev/null and b/data/images/logo_small.png differ
diff --git a/data/images/mystrale.jpg b/data/images/mystrale.jpg
new file mode 100644 (file)
index 0000000..31edf4a
Binary files /dev/null and b/data/images/mystrale.jpg differ
diff --git a/data/images/mystrale_2.jpg b/data/images/mystrale_2.jpg
new file mode 100644 (file)
index 0000000..88d86d6
Binary files /dev/null and b/data/images/mystrale_2.jpg differ
diff --git a/data/images/panel_01.jpg b/data/images/panel_01.jpg
new file mode 100644 (file)
index 0000000..46fbdb9
Binary files /dev/null and b/data/images/panel_01.jpg differ
diff --git a/data/images/parking.png b/data/images/parking.png
new file mode 100644 (file)
index 0000000..0a3d801
Binary files /dev/null and b/data/images/parking.png differ
diff --git a/data/images/plant_01.jpg b/data/images/plant_01.jpg
new file mode 100644 (file)
index 0000000..f1714dd
Binary files /dev/null and b/data/images/plant_01.jpg differ
diff --git a/data/images/rock_01.jpg b/data/images/rock_01.jpg
new file mode 100644 (file)
index 0000000..c50ccb3
Binary files /dev/null and b/data/images/rock_01.jpg differ
diff --git a/data/images/rock_02.jpg b/data/images/rock_02.jpg
new file mode 100644 (file)
index 0000000..04aea8a
Binary files /dev/null and b/data/images/rock_02.jpg differ
diff --git a/data/images/sky_01.jpg b/data/images/sky_01.jpg
new file mode 100644 (file)
index 0000000..22f3050
Binary files /dev/null and b/data/images/sky_01.jpg differ
diff --git a/data/images/sky_02.jpg b/data/images/sky_02.jpg
new file mode 100644 (file)
index 0000000..d0d7448
Binary files /dev/null and b/data/images/sky_02.jpg differ
diff --git a/data/images/sky_03.jpg b/data/images/sky_03.jpg
new file mode 100644 (file)
index 0000000..cbad02a
Binary files /dev/null and b/data/images/sky_03.jpg differ
diff --git a/data/images/sky_04.jpg b/data/images/sky_04.jpg
new file mode 100644 (file)
index 0000000..c5cbc18
Binary files /dev/null and b/data/images/sky_04.jpg differ
diff --git a/data/images/wood_01.jpg b/data/images/wood_01.jpg
new file mode 100644 (file)
index 0000000..89f1006
Binary files /dev/null and b/data/images/wood_01.jpg differ
diff --git a/data/objects/Makefile.am b/data/objects/Makefile.am
new file mode 100644 (file)
index 0000000..0f80b6c
--- /dev/null
@@ -0,0 +1,50 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+EDJE_CC = @edje_cc@
+EDJE_FLAGS = -v -id $(top_srcdir)/data/objects -fd $(top_srcdir)/data/objects
+
+filesdir = $(datadir)/elementary/objects
+
+files_DATA = test.edj multip.edj colorpreview.edj cursors.edj font_preview.edj
+
+EXTRA_DIST = \
+test.edc \
+multip.edc \
+colorpreview.edc \
+cursors.edc \
+font_preview.edc \
+grid_bg.png \
+over.png \
+under.png \
+sky.jpg \
+clo.png \
+cross.png
+
+test.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/objects/test.edc \
+       $(top_builddir)/data/objects/test.edj
+
+multip.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/objects/multip.edc \
+       $(top_builddir)/data/objects/multip.edj
+
+colorpreview.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/objects/colorpreview.edc \
+       $(top_builddir)/data/objects/colorpreview.edj
+
+cursors.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/objects/cursors.edc \
+       $(top_builddir)/data/objects/cursors.edj
+
+font_preview.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/objects/font_preview.edc \
+       $(top_builddir)/data/objects/font_preview.edj
+
+clean-local:
+       rm -f *.edj
diff --git a/data/objects/clo.png b/data/objects/clo.png
new file mode 100644 (file)
index 0000000..dedfc51
Binary files /dev/null and b/data/objects/clo.png differ
diff --git a/data/objects/colorpreview.edc b/data/objects/colorpreview.edc
new file mode 100644 (file)
index 0000000..77d1441
--- /dev/null
@@ -0,0 +1,22 @@
+images {
+   image: "grid_bg.png" COMP;
+}
+
+collections {
+   group { name: "main";
+      parts {
+         part { name: "Grid";
+            type: IMAGE;
+            description { state: "default" 0;
+               image.normal: "grid_bg.png";
+            }
+         }
+         part { name: "ColorPreview";
+            type: SWALLOW;
+            mouse_events: 0;
+            description { state: "default" 0;
+            }
+         }
+      }
+   }
+}
diff --git a/data/objects/cross.png b/data/objects/cross.png
new file mode 100644 (file)
index 0000000..9670d7f
Binary files /dev/null and b/data/objects/cross.png differ
diff --git a/data/objects/cursors.edc b/data/objects/cursors.edc
new file mode 100644 (file)
index 0000000..a943037
--- /dev/null
@@ -0,0 +1,80 @@
+/////////////////////////////////////////////////////////////////////////////
+// CURSOR
+/////////////////////////////////////////////////////////////////////////////
+collections {
+   group { name: "elm/cursor/hand2/default";
+       min: 30 30;
+       max: 30 30;
+       data {
+           item: "hot_x" "0";
+           item: "hot_y" "0";
+       }
+      parts {
+         part { name: "base";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               color: 0 255 0 255;
+            }
+         }
+      }
+   }
+
+   group { name: "elm/cursor/hand3/default";
+       min: 30 30;
+       max: 30 30;
+       data {
+           item: "hot_x" "0";
+           item: "hot_y" "0";
+       }
+      parts {
+         part { name: "base";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               color: 255 0 0 255;
+            }
+            description { state: "blue" 0.0;
+               color: 0 0 255 255;
+            }
+         }
+      }
+      programs {
+        program { name: "load";
+           signal: "load";
+           source: "";
+            after: "go_blue";
+         }
+        program { name: "go_blue";
+           action: STATE_SET "blue" 0.0;
+           transition: LINEAR 1;
+           target: "base";
+           after: "go_red";
+        }
+        program { name: "go_red";
+           action: STATE_SET "default" 0.0;
+           transition: LINEAR 1;
+           target: "base";
+           after: "go_blue";
+        }
+      }
+   }
+
+   group { name: "elm/cursor/hand3/transparent";
+       min: 30 30;
+       max: 30 30;
+       data {
+           item: "hot_x" "0";
+           item: "hot_y" "0";
+       }
+      parts {
+         part { name: "base";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               color: 255 0 0 120;
+            }
+         }
+      }
+   }
+}
diff --git a/data/objects/font_preview.edc b/data/objects/font_preview.edc
new file mode 100644 (file)
index 0000000..302c2e8
--- /dev/null
@@ -0,0 +1,40 @@
+color_classes {
+   color_class {
+      name: "entry_text";
+      color: 0 0 0 255;
+   }
+}
+
+collections {
+
+   group { name: "font_preview";
+      parts {
+
+         /* some fonts have weird alignments, thus they overflow badly */
+         part { name: "clipper";
+            type: RECT;
+            description {
+               state: "default" 0.0;
+            }
+         }
+
+         part { name: "elm.text";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            clip_to: "clipper";
+            description {
+               state: "default" 0.0;
+               color_class: "entry_text";
+               text {
+                  font: "Sans";
+                  min: 0 1;
+                  size: 10;
+                  align: 0.5 0.5;
+                  text_class: "font_preview";
+               }
+            }
+         }
+      }
+   }
+}
diff --git a/data/objects/grid_bg.png b/data/objects/grid_bg.png
new file mode 100644 (file)
index 0000000..7141658
Binary files /dev/null and b/data/objects/grid_bg.png differ
diff --git a/data/objects/multip.edc b/data/objects/multip.edc
new file mode 100644 (file)
index 0000000..66be6bb
--- /dev/null
@@ -0,0 +1,17 @@
+collections {
+   group { name: "point";
+      images {
+        image: "cross.png" COMP;
+      }
+      parts {
+        part { name: "sky";
+            mouse_events: 0;
+           description { state: "default" 0.0;
+               min: 301 301;
+              image.normal: "cross.png";
+           }
+        }
+      }
+   }
+}
+        
diff --git a/data/objects/over.png b/data/objects/over.png
new file mode 100644 (file)
index 0000000..5303e2d
Binary files /dev/null and b/data/objects/over.png differ
diff --git a/data/objects/sky.jpg b/data/objects/sky.jpg
new file mode 100644 (file)
index 0000000..6132e7c
Binary files /dev/null and b/data/objects/sky.jpg differ
diff --git a/data/objects/test.edc b/data/objects/test.edc
new file mode 100644 (file)
index 0000000..8efdca8
--- /dev/null
@@ -0,0 +1,698 @@
+collections {
+   group { name: "layout";
+      images {
+        image: "over.png" COMP;
+        image: "under.png" COMP;
+        image: "sky.jpg" LOSSY 80;
+        image: "clo.png" LOSSY 60;
+      }
+      parts {
+         part { name: "clip";
+            type: RECT;
+            description { state: "default" 0.0;
+            }
+         }
+        part { name: "sky";
+            mouse_events: 0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              aspect: 2.6225 2.6225;
+              aspect_preference: NONE;
+              image.normal: "sky.jpg";
+           }
+           description { state: "drift" 0.0;
+               inherit: "default" 0.0;
+               fill {
+                  origin {
+                     relative: 1.0 0.0;
+                     offset: 0 0;
+                  }
+               }
+           }
+        }
+        part { name: "under";
+            mouse_events: 0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              align: 0.5 0.0;
+              aspect: 1.486068111 1.486068111;
+              aspect_preference: HORIZONTAL;
+              image.normal: "under.png";
+           }
+        }
+        part { name: "text";
+           type: TEXT;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              color: 255 255 0 255;
+              rel1 {
+                 relative: 0.3 0.02;
+              }
+              rel2 {
+                 relative: 0.6 0.12;
+              }
+              align: 0.5 0.5;
+              text {
+                 font: "Sans:style=Bold";
+                 size: 14;
+                 min: 1 1;
+                 text: "some edje text here";
+              }
+           }
+        }
+        part { name: "element1";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                 relative: 0.2 0.2;
+              }
+              rel2 {
+                 relative: 0.4 0.3;
+              }
+           }
+        }
+        part { name: "element2";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                 relative: 0.6 0.3;
+              }
+              rel2 {
+                 relative: 0.9 0.5;
+              }
+           }
+        }
+        part { name: "element3";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                 relative: 0.1 0.7;
+              }
+              rel2 {
+                 relative: 0.9 0.9;
+              }
+           }
+        }
+        part { name: "over";
+            mouse_events: 0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              align: 0.0 1.0;
+              aspect: 2.238095238 2.238095238;
+              max: 329 147;
+              aspect_preference: HORIZONTAL;
+              image.normal: "over.png";
+           }
+        }
+         part { name: "clo";
+            mouse_events: 0;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               fill {
+                  smooth: 0;
+                  origin {
+                     relative: 0.0 0.0;
+                     offset: 0 0;
+                  }
+                  size {
+                     relative: 1.84722 1.0;
+                     offset: 0 0;
+                  }
+               }
+               image.normal: "clo.png";
+            }
+            description { state: "drift" 0.0;
+               inherit: "default" 0.0;
+               fill {
+                  origin {
+                     relative: 1.84722 0.0;
+                     offset: 0 0;
+                  }
+                  size {
+                     relative: 1.84722 1.0;
+                     offset: 0 0;
+                  }
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "anim1";
+            signal: "load";
+            source: "";
+            action: STATE_SET "drift" 0.0;
+            transition: LINEAR 10.0;
+            target: "clo";
+            after: "anim2";
+         }
+         program { name: "anim2";
+            action: STATE_SET "default" 0.0;
+            target: "clo";
+            after: "anim1";
+         }
+         program { name: "anim3";
+            signal: "load";
+            source: "";
+            action: STATE_SET "drift" 0.0;
+            transition: LINEAR 40.0;
+            target: "sky";
+            after: "anim4";
+         }
+         program { name: "anim4";
+            action: STATE_SET "default" 0.0;
+            target: "sky";
+            after: "anim3";
+         }
+      }
+   }
+   group { name: "layout2";
+      images {
+        image: "over.png" COMP;
+        image: "under.png" COMP;
+        image: "sky.jpg" LOSSY 80;
+        image: "clo.png" LOSSY 60;
+      }
+      parts {
+         part { name: "clip";
+            type: RECT;
+            description { state: "default" 0.0;
+            }
+         }
+        part { name: "sky";
+            mouse_events: 0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              aspect: 2.6225 2.6225;
+              aspect_preference: NONE;
+              image.normal: "sky.jpg";
+           }
+           description { state: "drift" 0.0;
+               inherit: "default" 0.0;
+               fill {
+                  origin {
+                     relative: 1.0 0.0;
+                     offset: 0 0;
+                  }
+               }
+           }
+        }
+        part { name: "under";
+            mouse_events: 0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              align: 0.5 0.0;
+              aspect: 1.486068111 1.486068111;
+              aspect_preference: HORIZONTAL;
+              image.normal: "under.png";
+           }
+        }
+        part { name: "text";
+           type: TEXT;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              color: 255 255 0 255;
+              rel1 {
+                 relative: 0.3 0.02;
+              }
+              rel2 {
+                 relative: 0.6 0.12;
+              }
+              align: 0.5 0.5;
+              text {
+                 font: "Sans:style=Bold";
+                 size: 14;
+                 min: 1 1;
+                 text: "some edje text here";
+              }
+           }
+        }
+        part { name: "element1";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                 relative: 0.2 0.2;
+              }
+              rel2 {
+                 relative: 0.4 0.3;
+              }
+           }
+        }
+        part { name: "element2";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                 relative: 0.6 0.3;
+              }
+              rel2 {
+                 relative: 0.9 0.5;
+              }
+           }
+        }
+        part { name: "element3";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                 relative: 0.1 0.7;
+              }
+              rel2 {
+                 relative: 0.9 0.9;
+              }
+           }
+        }
+        part { name: "over";
+            mouse_events: 0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              align: 0.0 1.0;
+              aspect: 2.238095238 2.238095238;
+              max: 329 147;
+              aspect_preference: HORIZONTAL;
+              image.normal: "over.png";
+           }
+        }
+         part { name: "clo";
+            mouse_events: 0;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               fill {
+                  smooth: 0;
+                  origin {
+                     relative: 0.0 0.0;
+                     offset: 0 0;
+                  }
+                  size {
+                     relative: 1.84722 1.0;
+                     offset: 0 0;
+                  }
+               }
+               image.normal: "clo.png";
+            }
+            description { state: "drift" 0.0;
+               inherit: "default" 0.0;
+               fill {
+                  origin {
+                     relative: 1.84722 0.0;
+                     offset: 0 0;
+                  }
+                  size {
+                     relative: 1.84722 1.0;
+                     offset: 0 0;
+                  }
+               }
+            }
+         }
+      }
+   }
+   group { name: "launcher_page";
+      parts {
+         part { name: "slot.0.0"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.0  0.0;
+              }
+              rel2 { relative: 0.25 0.25;
+              }
+            }
+         }
+         part { name: "slot.1.0"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.25 0.0;
+              }
+              rel2 { relative: 0.50 0.25;
+              }
+            }
+         }
+         part { name: "slot.2.0"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.50 0.0;
+              }
+              rel2 { relative: 0.75 0.25;
+              }
+            }
+         }
+         part { name: "slot.3.0"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.75 0.0;
+              }
+              rel2 { relative: 1.00 0.25;
+              }
+            }
+         }
+         part { name: "slot.0.1"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.0  0.25;
+              }
+              rel2 { relative: 0.25 0.50;
+              }
+            }
+         }
+         part { name: "slot.1.1"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.25 0.25;
+              }
+              rel2 { relative: 0.50 0.50;
+              }
+            }
+         }
+         part { name: "slot.2.1"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.50 0.25;
+              }
+              rel2 { relative: 0.75 0.50;
+              }
+            }
+         }
+         part { name: "slot.3.1"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.75 0.25;
+              }
+              rel2 { relative: 1.00 0.50;
+              }
+            }
+         }
+         part { name: "slot.0.2"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.0  0.50;
+              }
+              rel2 { relative: 0.25 0.75;
+              }
+            }
+         }
+         part { name: "slot.1.2"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.25 0.50;
+              }
+              rel2 { relative: 0.50 0.75;
+              }
+            }
+         }
+         part { name: "slot.2.2"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.50 0.50;
+              }
+              rel2 { relative: 0.75 0.75;
+              }
+            }
+         }
+         part { name: "slot.3.2"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.75 0.50;
+              }
+              rel2 { relative: 1.00 0.75;
+              }
+            }
+         }
+         part { name: "slot.0.3"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.0  0.75;
+              }
+              rel2 { relative: 0.25 1.00;
+              }
+            }
+         }
+         part { name: "slot.1.3"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.25 0.75;
+              }
+              rel2 { relative: 0.50 1.00;
+              }
+            }
+         }
+         part { name: "slot.2.3"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.50 0.75;
+              }
+              rel2 { relative: 0.75 1.00;
+              }
+            }
+         }
+         part { name: "slot.3.3"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.75 0.75;
+              }
+              rel2 { relative: 1.00 1.00;
+              }
+            }
+         }
+      }
+   }
+   group { name: "launcher_icon";
+      parts {
+         part { name: "slot"; type: SWALLOW;
+            description { state: "default" 0.0;
+              rel1 { relative: 0.0 0.0;
+              }
+              rel2 { relative: 1.00 0.00;
+                to_y: "label";
+              }
+            }
+            description { state: "drag1" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: -5 -3;
+              rel2.offset: -5 -3;
+            }
+            description { state: "drag2" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: 10 3;
+              rel2.offset: 10 3;
+            }
+            description { state: "drag3" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: -1  6;
+              rel2.offset: -1  6;
+            }
+         }
+         part { name: "label"; type: TEXT;
+            effect: SOFT_SHADOW;
+            scale: 1;
+            description { state: "default" 0.0;
+              fixed: 1 1;
+              align: 0.5 1.0;
+              rel1 { relative: 0.0  1.00;
+              }
+              rel2 { relative: 1.00 1.00;
+              }
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                font: "Sans:style=Bold,Edje-Vera-Bold";
+                size: 10;
+                min: 0 1;
+                max: 1 1;
+                align: 0.5 0.0;
+              }
+            }
+            description { state: "hi" 0.0;
+              inherit: "default" 0.0;
+              color: 255 0 0 255;
+              color3: 0 0 0 255;
+            }
+            description { state: "drag1" 0.0;
+              inherit: "default" 0.0;
+              color: 255 0 0 255;
+              color3: 0 0 0 255;
+              rel1.offset: -5 -3;
+              rel2.offset: -5 -3;
+            }
+            description { state: "drag2" 0.0;
+              inherit: "default" 0.0;
+              color: 255 0 0 255;
+              color3: 0 0 0 255;
+              rel1.offset: 10 3;
+              rel2.offset: 10 3;
+            }
+            description { state: "drag3" 0.0;
+              inherit: "default" 0.0;
+              color: 255 0 0 255;
+              color3: 0 0 0 255;
+              rel1.offset: -1  6;
+              rel2.offset: -1  6;
+            }
+         }
+      }
+      programs {
+         program { name: "click";
+            signal: "click"; source: "app";
+            action: STATE_SET "hi" 0.0;
+            transition: LINEAR 0.5;
+            target: "label";
+         }
+         program { name: "drag1";
+            signal: "drag"; source: "app";
+            action: STATE_SET "drag1" 0.0;
+            transition: LINEAR 0.1;
+            target: "label";
+            target: "slot";
+            after: "drag2";
+         }
+         program { name: "drag2";
+            action: STATE_SET "drag2" 0.0;
+            transition: LINEAR 0.2;
+            target: "label";
+            target: "slot";
+            after: "drag3";
+         }
+         program { name: "drag3";
+            action: STATE_SET "drag3" 0.0;
+            transition: LINEAR 0.1;
+            target: "label";
+            target: "slot";
+            after: "drag1";
+         }
+         program { name: "drop";
+            signal: "drop"; source: "app";
+            action: STATE_SET "default" 0.0;
+            target: "label";
+            target: "slot";
+         }
+         program { name: "unclick";
+            signal: "unclick"; source: "app";
+            action: STATE_SET "default" 0.0;
+            transition: LINEAR 0.5;
+            target: "label";
+            target: "slot";
+         }
+         program { name: "cancel";
+            signal: "cancel"; source: "app";
+            action: STATE_SET "default" 0.0;
+            transition: LINEAR 0.5;
+            target: "label";
+            target: "slot";
+         }
+      }
+   }
+   group { name: "twolines";
+      parts {
+         part { name: "clip";
+            type: RECT;
+            description { state: "default" 0.0;
+            }
+         }
+         part { name: "under";
+            mouse_events: 0;
+            clip_to: "clip";
+            type: RECT;
+            description { state: "default" 0.0;
+               color: 0 128 200 30;
+            }
+         }
+         part { name: "element1";
+            type: SWALLOW;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  relative: 1.0 0.5;
+                  offset: -5 -3;
+               }
+            }
+         }
+         part { name: "element2";
+            type: SWALLOW;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0 0.5;
+                  offset: 4 2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -5 -5;
+               }
+            }
+         }
+      }
+   }
+   group { name: "bg_overlay";
+      images {
+        image: "clo.png" LOSSY 60;
+      }
+      parts {
+         part { name: "clip";
+            type: RECT;
+            description { state: "default" 0.0;
+            }
+         }
+         part { name: "clo";
+            mouse_events: 0;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               fill {
+                  smooth: 0;
+                  origin {
+                     relative: 0.0 0.0;
+                     offset: 0 0;
+                  }
+                  size {
+                     relative: 1.84722 1.0;
+                     offset: 0 0;
+                  }
+               }
+               image.normal: "clo.png";
+            }
+            description { state: "drift" 0.0;
+               inherit: "default" 0.0;
+               fill {
+                  origin {
+                     relative: 1.84722 0.0;
+                     offset: 0 0;
+                  }
+                  size {
+                     relative: 1.84722 1.0;
+                     offset: 0 0;
+                  }
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "anim1";
+            signal: "load";
+            source: "";
+            action: STATE_SET "drift" 0.0;
+            transition: LINEAR 10.0;
+            target: "clo";
+            after: "anim2";
+         }
+         program { name: "anim2";
+            action: STATE_SET "default" 0.0;
+            target: "clo";
+            after: "anim1";
+         }
+      }
+   }
+group {
+      name: "test/layout";
+      images {
+        image: "sky.jpg" LOSSY 80;
+      }
+      parts {
+            part {
+                 name: "bg";
+                 description {
+                     state: "default" 0.0;
+                     color: 255 255 255 100;
+                     image.normal: "sky.jpg";
+                 }
+            }
+            part {
+                 name: "swallow";
+                 type: SWALLOW;
+                 description {
+                     state: "default" 0.0;
+                     rel1.offset: 8 8;
+                     rel2.offset: -7 -7;
+                 }
+            }
+      }
+}
+}
+        
diff --git a/data/objects/under.png b/data/objects/under.png
new file mode 100644 (file)
index 0000000..91cb3fb
Binary files /dev/null and b/data/objects/under.png differ
diff --git a/data/themes/Makefile.am b/data/themes/Makefile.am
new file mode 100644 (file)
index 0000000..4e36cc0
--- /dev/null
@@ -0,0 +1,233 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+EDJE_CC = @edje_cc@
+EDJE_FLAGS = -v -id $(top_srcdir)/data/themes -fd $(top_srcdir)/data/themes
+
+filesdir = $(datadir)/elementary/themes
+files_DATA = default.edj default-desktop.edj
+
+EXTRA_DIST = \
+default.edc \
+default-desktop.edc \
+arrow_down.png \
+arrow_up.png \
+bar_shine.png \
+bt_base1.png \
+bt_base2.png \
+bt_bases.png \
+bt_basew.png \
+bt_glow.png \
+bt_hilight.png \
+bt_hilightw.png \
+bt_shine.png \
+bt_sm_base1.png \
+bt_sm_base2.png \
+bt_sm_hilight.png \
+bt_sm_shine.png \
+bt_dis_base.png \
+bt_dis_hilight.png \
+dia_botshad.png \
+dia_grad.png \
+dia_topshad.png \
+frame_1.png \
+frame_2.png \
+flip_0b.png \
+flip_0t.png \
+flip_1b.png \
+flip_1t.png \
+flip_2b.png \
+flip_2t.png \
+flip_3b.png \
+flip_3t.png \
+flip_4b.png \
+flip_4t.png \
+flip_5b.png \
+flip_5t.png \
+flip_6b.png \
+flip_6t.png \
+flip_7b.png \
+flip_7t.png \
+flip_8b.png \
+flip_8t.png \
+flip_9b.png \
+flip_9t.png \
+flip_amb.png \
+flip_amt.png \
+flip_base.png \
+flip_base_shad.png \
+flip_pmb.png \
+flip_pmt.png \
+flip_shad.png \
+flip_t.png \
+flip_b.png \
+head.png \
+sb_runnerh.png \
+sb_runnerv.png \
+shelf_inset.png \
+tog_base.png \
+tog_dis_base.png \
+shad_circ.png \
+bt_dis_base.png \
+bt_dis_hilight.png \
+outdent-top.png \
+outdent-bottom.png \
+updown.png \
+leftright.png \
+hoversel_entry_bg.png \
+cur_box.png \
+cur_hi.png \
+cur_shad.png \
+cur_shine.png \
+cur_glow.png \
+bubble.png \
+bubble_3.png \
+bubble_shine3.png \
+bubble_4.png \
+bubble_shine4.png \
+bubble_1.png \
+bubble_shine.png \
+bubble_2.png \
+icon_home.png \
+icon_close.png \
+icon_apps.png \
+icon_arrow_up.png \
+icon_arrow_down.png \
+icon_arrow_left.png \
+icon_arrow_right.png \
+bt_dis_shine.png \
+icon_left_arrow.png \
+icon_right_arrow.png \
+toolbar_sel.png \
+icon_chat.png \
+icon_clock.png \
+icon_delete.png \
+icon_edit.png \
+icon_refresh.png \
+icon_folder.png \
+icon_file.png \
+ilist_1.png \
+ilist_1_h.png \
+ilist_2.png \
+ilist_2_h.png \
+ilist_item_shadow.png \
+ilist_item_shadow_h.png \
+sl_bg.png \
+sl_bg_over.png \
+sl_bt_0.png \
+sl_bt_1.png \
+sl_bt_2.png \
+sl_bt_3.png \
+sl_bt2_0_0.png \
+sl_bt2_0_1.png \
+sl_bt2_0_2.png \
+sl_bt2_1.png \
+sl_bt2_2.png \
+sl_units.png \
+slv_bg.png \
+slv_bg_over.png \
+slv_units.png \
+check_base.png \
+check.png \
+check2.png \
+radio_base.png \
+radio.png \
+radio2.png \
+separator_h.png \
+separator_v.png \
+toolbar_separator_v.png \
+sp_bt_l.png \
+sp_bt_r.png \
+busy-1.png \
+busy-2.png \
+busy-3.png \
+busy-4.png \
+busy-5.png \
+busy-6.png \
+busy-7.png \
+busy-8.png \
+busy-9.png \
+arrow_right.png \
+arrow_left.png \
+bt_spinner_up.png \
+bt_spinner_down.png \
+bt_spinner_hilight.png \
+up.png \
+down.png \
+emo-angry.png \
+emo-angry-shout.png \
+emo-crazy-laugh.png \
+emo-evil-laugh.png \
+emo-evil.png \
+emo-goggle-smile.png \
+emo-grumpy.png \
+emo-grumpy-smile.png \
+emo-guilty.png \
+emo-guilty-smile.png \
+emo-haha.png \
+emo-half-smile.png \
+emo-happy-panting.png \
+emo-happy.png \
+emo-indifferent.png \
+emo-kiss.png \
+emo-knowing-grin.png \
+emo-laugh.png \
+emo-little-bit-sorry.png \
+emo-love-lots.png \
+emo-love.png \
+emo-minimal-smile.png \
+emo-not-happy.png \
+emo-not-impressed.png \
+emo-omg.png \
+emo-opensmile.png \
+emo-smile.png \
+emo-sorry.png \
+emo-squint-laugh.png \
+emo-surprised.png \
+emo-suspicious.png \
+emo-tongue-dangling.png \
+emo-tongue-poke.png \
+emo-uh.png \
+emo-unhappy.png \
+emo-very-sorry.png \
+emo-what.png \
+emo-wink.png \
+emo-worried.png \
+emo-wtf.png \
+map_item.png \
+map_item_2.png \
+shadow.png \
+black.png \
+tooltip-corner-top-left-tip.png \
+tooltip-base.png \
+tooltip-corner-bottom-left-tip.png \
+tooltip-edge-top-tip.png \
+tooltip-corner-bottom-right-tip.png \
+tooltip-edge-left-tip.png \
+tooltip-edge-bottom-tip.png \
+tooltip-edge-right-tip.png \
+tooltip-corner-top-right-tip.png \
+color_picker_alpha.png \
+color_picker_alpha_bg.png \
+color_picker_brightness.png \
+color_picker_color.png \
+color_picker_opacity.png \
+icon_arrow_down_left.png \
+icon_arrow_down_right.png \
+icon_arrow_up_left.png \
+icon_arrow_up_right.png \
+thumb_shadow.png \
+group_index.png
+
+default.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/themes/default.edc \
+       $(top_builddir)/data/themes/default.edj
+
+default-desktop.edj: Makefile $(EXTRA_DIST)
+       $(EDJE_CC) $(EDJE_FLAGS) \
+       $(top_srcdir)/data/themes/default-desktop.edc \
+       $(top_builddir)/data/themes/default-desktop.edj
+
+clean-local:
+       rm -f *.edj
diff --git a/data/themes/arrow_down.png b/data/themes/arrow_down.png
new file mode 100644 (file)
index 0000000..db81aac
Binary files /dev/null and b/data/themes/arrow_down.png differ
diff --git a/data/themes/arrow_down.xcf.gz b/data/themes/arrow_down.xcf.gz
new file mode 100644 (file)
index 0000000..3d4e89c
Binary files /dev/null and b/data/themes/arrow_down.xcf.gz differ
diff --git a/data/themes/arrow_left.png b/data/themes/arrow_left.png
new file mode 100644 (file)
index 0000000..fbe0795
Binary files /dev/null and b/data/themes/arrow_left.png differ
diff --git a/data/themes/arrow_right.png b/data/themes/arrow_right.png
new file mode 100644 (file)
index 0000000..268d6d1
Binary files /dev/null and b/data/themes/arrow_right.png differ
diff --git a/data/themes/arrow_up.png b/data/themes/arrow_up.png
new file mode 100644 (file)
index 0000000..a90fe93
Binary files /dev/null and b/data/themes/arrow_up.png differ
diff --git a/data/themes/arrow_up.xcf.gz b/data/themes/arrow_up.xcf.gz
new file mode 100644 (file)
index 0000000..977e24c
Binary files /dev/null and b/data/themes/arrow_up.xcf.gz differ
diff --git a/data/themes/bar_shine.png b/data/themes/bar_shine.png
new file mode 100644 (file)
index 0000000..95df605
Binary files /dev/null and b/data/themes/bar_shine.png differ
diff --git a/data/themes/black.png b/data/themes/black.png
new file mode 100644 (file)
index 0000000..28f520a
Binary files /dev/null and b/data/themes/black.png differ
diff --git a/data/themes/bt_base1.png b/data/themes/bt_base1.png
new file mode 100644 (file)
index 0000000..2d1f179
Binary files /dev/null and b/data/themes/bt_base1.png differ
diff --git a/data/themes/bt_base2.png b/data/themes/bt_base2.png
new file mode 100644 (file)
index 0000000..dd3e3ce
Binary files /dev/null and b/data/themes/bt_base2.png differ
diff --git a/data/themes/bt_bases.png b/data/themes/bt_bases.png
new file mode 100644 (file)
index 0000000..1b867fd
Binary files /dev/null and b/data/themes/bt_bases.png differ
diff --git a/data/themes/bt_basew.png b/data/themes/bt_basew.png
new file mode 100644 (file)
index 0000000..8d787dd
Binary files /dev/null and b/data/themes/bt_basew.png differ
diff --git a/data/themes/bt_dis_base.png b/data/themes/bt_dis_base.png
new file mode 100644 (file)
index 0000000..06f3dd5
Binary files /dev/null and b/data/themes/bt_dis_base.png differ
diff --git a/data/themes/bt_dis_hilight.png b/data/themes/bt_dis_hilight.png
new file mode 100644 (file)
index 0000000..e5cf7d3
Binary files /dev/null and b/data/themes/bt_dis_hilight.png differ
diff --git a/data/themes/bt_dis_shine.png b/data/themes/bt_dis_shine.png
new file mode 100644 (file)
index 0000000..20285be
Binary files /dev/null and b/data/themes/bt_dis_shine.png differ
diff --git a/data/themes/bt_glow.png b/data/themes/bt_glow.png
new file mode 100644 (file)
index 0000000..e995ff1
Binary files /dev/null and b/data/themes/bt_glow.png differ
diff --git a/data/themes/bt_hilight.png b/data/themes/bt_hilight.png
new file mode 100644 (file)
index 0000000..3b7fe5b
Binary files /dev/null and b/data/themes/bt_hilight.png differ
diff --git a/data/themes/bt_hilightw.png b/data/themes/bt_hilightw.png
new file mode 100644 (file)
index 0000000..b97a4f8
Binary files /dev/null and b/data/themes/bt_hilightw.png differ
diff --git a/data/themes/bt_shine.png b/data/themes/bt_shine.png
new file mode 100644 (file)
index 0000000..a58bdee
Binary files /dev/null and b/data/themes/bt_shine.png differ
diff --git a/data/themes/bt_sm_base1.png b/data/themes/bt_sm_base1.png
new file mode 100644 (file)
index 0000000..c37e182
Binary files /dev/null and b/data/themes/bt_sm_base1.png differ
diff --git a/data/themes/bt_sm_base2.png b/data/themes/bt_sm_base2.png
new file mode 100644 (file)
index 0000000..f159648
Binary files /dev/null and b/data/themes/bt_sm_base2.png differ
diff --git a/data/themes/bt_sm_hilight.png b/data/themes/bt_sm_hilight.png
new file mode 100644 (file)
index 0000000..63899ca
Binary files /dev/null and b/data/themes/bt_sm_hilight.png differ
diff --git a/data/themes/bt_sm_shine.png b/data/themes/bt_sm_shine.png
new file mode 100644 (file)
index 0000000..23bf311
Binary files /dev/null and b/data/themes/bt_sm_shine.png differ
diff --git a/data/themes/bt_spinner_down.png b/data/themes/bt_spinner_down.png
new file mode 100644 (file)
index 0000000..233f2a9
Binary files /dev/null and b/data/themes/bt_spinner_down.png differ
diff --git a/data/themes/bt_spinner_hilight.png b/data/themes/bt_spinner_hilight.png
new file mode 100644 (file)
index 0000000..55d50b8
Binary files /dev/null and b/data/themes/bt_spinner_hilight.png differ
diff --git a/data/themes/bt_spinner_up.png b/data/themes/bt_spinner_up.png
new file mode 100644 (file)
index 0000000..ea351be
Binary files /dev/null and b/data/themes/bt_spinner_up.png differ
diff --git a/data/themes/bubble.png b/data/themes/bubble.png
new file mode 100644 (file)
index 0000000..78b831b
Binary files /dev/null and b/data/themes/bubble.png differ
diff --git a/data/themes/bubble_1.png b/data/themes/bubble_1.png
new file mode 100644 (file)
index 0000000..fd6d00c
Binary files /dev/null and b/data/themes/bubble_1.png differ
diff --git a/data/themes/bubble_2.png b/data/themes/bubble_2.png
new file mode 100644 (file)
index 0000000..6e1e847
Binary files /dev/null and b/data/themes/bubble_2.png differ
diff --git a/data/themes/bubble_3.png b/data/themes/bubble_3.png
new file mode 100644 (file)
index 0000000..cbdcf9c
Binary files /dev/null and b/data/themes/bubble_3.png differ
diff --git a/data/themes/bubble_4.png b/data/themes/bubble_4.png
new file mode 100644 (file)
index 0000000..5eefbff
Binary files /dev/null and b/data/themes/bubble_4.png differ
diff --git a/data/themes/bubble_shine.png b/data/themes/bubble_shine.png
new file mode 100644 (file)
index 0000000..33fd1d8
Binary files /dev/null and b/data/themes/bubble_shine.png differ
diff --git a/data/themes/bubble_shine3.png b/data/themes/bubble_shine3.png
new file mode 100644 (file)
index 0000000..398062f
Binary files /dev/null and b/data/themes/bubble_shine3.png differ
diff --git a/data/themes/bubble_shine4.png b/data/themes/bubble_shine4.png
new file mode 100644 (file)
index 0000000..9ab6fd0
Binary files /dev/null and b/data/themes/bubble_shine4.png differ
diff --git a/data/themes/busy-1.png b/data/themes/busy-1.png
new file mode 100644 (file)
index 0000000..0997dee
Binary files /dev/null and b/data/themes/busy-1.png differ
diff --git a/data/themes/busy-2.png b/data/themes/busy-2.png
new file mode 100644 (file)
index 0000000..71c65a4
Binary files /dev/null and b/data/themes/busy-2.png differ
diff --git a/data/themes/busy-3.png b/data/themes/busy-3.png
new file mode 100644 (file)
index 0000000..96e63ab
Binary files /dev/null and b/data/themes/busy-3.png differ
diff --git a/data/themes/busy-4.png b/data/themes/busy-4.png
new file mode 100644 (file)
index 0000000..4ecb44c
Binary files /dev/null and b/data/themes/busy-4.png differ
diff --git a/data/themes/busy-5.png b/data/themes/busy-5.png
new file mode 100644 (file)
index 0000000..2978f49
Binary files /dev/null and b/data/themes/busy-5.png differ
diff --git a/data/themes/busy-6.png b/data/themes/busy-6.png
new file mode 100644 (file)
index 0000000..a73d583
Binary files /dev/null and b/data/themes/busy-6.png differ
diff --git a/data/themes/busy-7.png b/data/themes/busy-7.png
new file mode 100644 (file)
index 0000000..2cc0f80
Binary files /dev/null and b/data/themes/busy-7.png differ
diff --git a/data/themes/busy-8.png b/data/themes/busy-8.png
new file mode 100644 (file)
index 0000000..c07cddc
Binary files /dev/null and b/data/themes/busy-8.png differ
diff --git a/data/themes/busy-9.png b/data/themes/busy-9.png
new file mode 100644 (file)
index 0000000..9fdf098
Binary files /dev/null and b/data/themes/busy-9.png differ
diff --git a/data/themes/check.png b/data/themes/check.png
new file mode 100644 (file)
index 0000000..7d58e85
Binary files /dev/null and b/data/themes/check.png differ
diff --git a/data/themes/check2.png b/data/themes/check2.png
new file mode 100644 (file)
index 0000000..1748d5d
Binary files /dev/null and b/data/themes/check2.png differ
diff --git a/data/themes/check_base.png b/data/themes/check_base.png
new file mode 100644 (file)
index 0000000..96481c9
Binary files /dev/null and b/data/themes/check_base.png differ
diff --git a/data/themes/color_picker_alpha.png b/data/themes/color_picker_alpha.png
new file mode 100644 (file)
index 0000000..09cbe77
Binary files /dev/null and b/data/themes/color_picker_alpha.png differ
diff --git a/data/themes/color_picker_alpha_bg.png b/data/themes/color_picker_alpha_bg.png
new file mode 100644 (file)
index 0000000..6d144d7
Binary files /dev/null and b/data/themes/color_picker_alpha_bg.png differ
diff --git a/data/themes/color_picker_brightness.png b/data/themes/color_picker_brightness.png
new file mode 100644 (file)
index 0000000..b2bbf5d
Binary files /dev/null and b/data/themes/color_picker_brightness.png differ
diff --git a/data/themes/color_picker_color.png b/data/themes/color_picker_color.png
new file mode 100644 (file)
index 0000000..1c609f8
Binary files /dev/null and b/data/themes/color_picker_color.png differ
diff --git a/data/themes/color_picker_opacity.png b/data/themes/color_picker_opacity.png
new file mode 100644 (file)
index 0000000..370ea1c
Binary files /dev/null and b/data/themes/color_picker_opacity.png differ
diff --git a/data/themes/cur_box.png b/data/themes/cur_box.png
new file mode 100644 (file)
index 0000000..136b8c8
Binary files /dev/null and b/data/themes/cur_box.png differ
diff --git a/data/themes/cur_glow.png b/data/themes/cur_glow.png
new file mode 100644 (file)
index 0000000..fd922bd
Binary files /dev/null and b/data/themes/cur_glow.png differ
diff --git a/data/themes/cur_hi.png b/data/themes/cur_hi.png
new file mode 100644 (file)
index 0000000..cbafef8
Binary files /dev/null and b/data/themes/cur_hi.png differ
diff --git a/data/themes/cur_shad.png b/data/themes/cur_shad.png
new file mode 100644 (file)
index 0000000..3e899de
Binary files /dev/null and b/data/themes/cur_shad.png differ
diff --git a/data/themes/cur_shine.png b/data/themes/cur_shine.png
new file mode 100644 (file)
index 0000000..6df5a6d
Binary files /dev/null and b/data/themes/cur_shine.png differ
diff --git a/data/themes/default-desktop.edc b/data/themes/default-desktop.edc
new file mode 100644 (file)
index 0000000..c8d1feb
--- /dev/null
@@ -0,0 +1,1351 @@
+externals.external: "elm";
+
+#define SCROLLBARS_ADD() \
+            images { \
+                image: "bt_sm_base2.png" COMP; \
+                image: "bt_sm_shine.png" COMP; \
+                image: "bt_sm_hilight.png" COMP; \
+                image: "sb_runnerh.png" COMP; \
+                image: "sb_runnerv.png" COMP; \
+                image: "arrow_up.png" COMP; \
+                image: "arrow_down.png" COMP; \
+                image: "arrow_right.png" COMP; \
+                image: "arrow_left.png" COMP; \
+            } \
+            script { \
+                public sbvis_v, sbvis_h; \
+            } \
+            part { name: "elm.scrollbar.base"; \
+                type: SWALLOW; \
+                mouse_events: 0; \
+                description { state: "default" 0.0; \
+                    min: 0 0; \
+                    fixed: 1 1; \
+                    align: 0.0 0.0; \
+                    rel1.relative: 1.0 1.0; \
+                } \
+                description { state: "vertical" 0.0; \
+                    inherit: "default" 0.0; \
+                    min: 17 0; \
+                    align: 1.0 0.0; \
+                } \
+                description { state: "horizontal" 0.0; \
+                    inherit: "default" 0.0; \
+                    min: 0 17; \
+                    align: 0.0 1.0; \
+                } \
+                description { state: "both" 0.0; \
+                    inherit: "default" 0.0; \
+                    min: 17 17; \
+                    align: 1.0 1.0; \
+                } \
+            } \
+            part { name: "sb_vbar_clip_master"; \
+                type: RECT; \
+                mouse_events: 0; \
+                description { state: "default" 0.0; \
+                } \
+                description { state: "hidden" 0.0; \
+                    visible: 0; \
+                } \
+            } \
+            part { name: "sb_vbar_clip"; \
+                type: RECT; \
+                mouse_events: 0; \
+                clip_to: "sb_vbar_clip_master"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "sb_vbar_clip_master"; \
+                    rel2.to: "sb_vbar_clip_master"; \
+                } \
+                description { state: "hidden" 0.0; \
+                    inherit: "default" 0.0; \
+                    visible: 0; \
+                    max: 0 99999; \
+                } \
+            } \
+            part { name: "sb_vbar"; \
+                type: RECT; \
+                mouse_events: 0; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 17 0; \
+                    fixed: 1 1; \
+                    color: 0 0 0 0; \
+                    align: 0.5 0.5; \
+                    rel1 { \
+                        to_y: "sb_vbar_a1"; \
+                        to_x: "elm.scrollbar.base"; \
+                        relative: 0.0 1.0; \
+                        offset: 0 -1; \
+                    } \
+                    rel2 { \
+                        to_y: "sb_vbar_a2"; \
+                        relative: 1.0 0.0; \
+                        offset: -1 -2; \
+                    } \
+                } \
+            } \
+            part { name: "sb_vbar_runner"; \
+                mouse_events: 0; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 3 0; \
+                    max: 3 99999; \
+                    fixed: 1 1; \
+                    align: 1.0 0.5; \
+                    rel1 { \
+                        to: "sb_vbar"; \
+                        relative: 0.5 0.0; \
+                        offset: 0 2; \
+                    } \
+                    rel2 { \
+                        to: "sb_vbar"; \
+                        relative: 0.5 1.0; \
+                        offset: 0 -2; \
+                    } \
+                    image { \
+                        normal: "sb_runnerv.png"; \
+                        border: 0 0 4 4; \
+                    } \
+                    fill.smooth: 0; \
+                } \
+            } \
+            part { name: "sb_vbar_p1"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    color: 0 0 0 0; \
+                    fixed: 1 1; \
+                    rel1 { \
+                        to: "sb_vbar_a1"; \
+                        relative: 0.0 1.0; \
+                    } \
+                    rel2 { \
+                        to: "elm.dragable.vbar"; \
+                        relative: 1.0 0.0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_vbar_p2"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    color: 0 0 0 0; \
+                    fixed: 1 1; \
+                    rel1 { \
+                        to: "elm.dragable.vbar"; \
+                        relative: 0.0 1.0; \
+                    } \
+                    rel2 { \
+                        to: "sb_vbar_a2"; \
+                        relative: 1.0 0.0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_vbar_a1"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 17 17; \
+                    fixed: 1 1; \
+                    align: 0.5 0.0; \
+                    aspect: 1.0 1.0; \
+                    aspect_preference: HORIZONTAL; \
+                    color: 0 0 0 0; \
+                    rel1 { \
+                        to_y: "sb_vbar_clip"; \
+                        to_x: "elm.scrollbar.base"; \
+                        relative: 0.0 0.0; \
+                        offset: 0 1; \
+                    } \
+                    rel2 { \
+                        to: "elm.scrollbar.base"; \
+                        relative: 1.0 0.0; \
+                        offset: -1 -2; \
+                    } \
+                } \
+            } \
+            part { name: "sb_vbar_a1_arrow"; \
+                mouse_events: 0; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "sb_vbar_a1"; \
+                    rel2.to: "sb_vbar_a1"; \
+                    image.normal: "arrow_up.png"; \
+                } \
+                description { state: "clicked" 0.0; \
+                    inherit: "default" 0.0; \
+                    rel1.offset: 0 -1; \
+                    rel2.offset: -1 -2; \
+                } \
+            } \
+            part { name: "sb_vbar_a2"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 17 17; \
+                    fixed: 1 1; \
+                    align: 0.5 1.0; \
+                    aspect: 1.0 1.0; \
+                    aspect_preference: HORIZONTAL; \
+                    color: 0 0 0 0; \
+                    rel1.to: "elm.scrollbar.base"; \
+                    rel2 { \
+                        to: "elm.scrollbar.base"; \
+                        relative: 1.0 0.0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_vbar_a2_arrow"; \
+                mouse_events: 0; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "sb_vbar_a2"; \
+                    rel2.to: "sb_vbar_a2"; \
+                    image.normal: "arrow_down.png"; \
+                } \
+                description { state: "clicked" 0.0; \
+                    inherit: "default" 0.0; \
+                    rel1.offset: 0 1; \
+                    rel2.offset: -1 0; \
+                } \
+            } \
+            part { name: "elm.dragable.vbar"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_vbar_clip"; \
+                dragable { \
+                    x: 0 0 0; \
+                    y: 1 1 0; \
+                    confine: "sb_vbar"; \
+                } \
+                description { state: "default" 0.0; \
+                    min: 17 17; \
+                    fixed: 1 1; \
+                    aspect: 1.0 0.5; \
+                    aspect_preference: VERTICAL; \
+                    align: 0.5 0.0; \
+                    color: 0 0 0 0; \
+                    rel1 { \
+                        to_y: "sb_vbar"; \
+                        to_x: "elm.scrollbar.base"; \
+                        relative: 0.0 0.0; \
+                    } \
+                    rel2.to_y: "sb_vbar"; \
+                } \
+            } \
+            part { name: "elm.dragable.vbar.image"; \
+                mouse_events: 0; \
+                clip_to: "sb_vbar_clip"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "elm.dragable.vbar"; \
+                    rel2.to: "elm.dragable.vbar"; \
+                    image { \
+                        normal: "bt_sm_base2.png"; \
+                        border: 6 6 6 6; \
+                    } \
+                } \
+            } \
+            part { name: "sb_vbar_over1"; \
+                clip_to: "sb_vbar_clip"; \
+                mouse_events: 0; \
+                description { state: "default" 0.0; \
+                    rel1.to: "elm.dragable.vbar.image"; \
+                    rel2 { \
+                        to: "elm.dragable.vbar.image"; \
+                        relative: 1.0 0.5; \
+                    } \
+                    image { \
+                        normal: "bt_sm_hilight.png"; \
+                        border: 6 6 6 0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_vbar_over2"; \
+                clip_to: "sb_vbar_clip"; \
+                mouse_events: 0; \
+                description { state: "default" 0.0; \
+                    rel1.to: "elm.dragable.vbar.image"; \
+                    rel2.to: "elm.dragable.vbar.image"; \
+                    image { \
+                        normal: "bt_sm_shine.png"; \
+                        border: 6 6 6 0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_clip_master"; \
+                type: RECT; \
+                mouse_events: 0; \
+                description { state: "default" 0.0; \
+                } \
+                description { state: "hidden" 0.0; \
+                    visible: 0; \
+                } \
+            } \
+            part { name: "sb_hbar_clip"; \
+                type: RECT; \
+                mouse_events: 0; \
+                clip_to: "sb_hbar_clip_master"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "sb_hbar_clip_master"; \
+                    rel2.to: "sb_hbar_clip_master"; \
+                } \
+                description { state: "hidden" 0.0; \
+                    inherit: "default" 0.0; \
+                    visible: 0; \
+                    max: 99999 0; \
+                } \
+            } \
+            part { name: "sb_hbar"; \
+                type: RECT; \
+                mouse_events: 0; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 0 17; \
+                    fixed: 1 1; \
+                    color: 0 0 0 0; \
+                    align: 0.5 0.5; \
+                    rel1 { \
+                        to_x: "sb_hbar_a1"; \
+                        to_y: "elm.scrollbar.base"; \
+                        relative: 1.0 0.0; \
+                        offset: -1 0; \
+                    } \
+                    rel2 { \
+                        to_x: "sb_hbar_a2"; \
+                        relative: 0.0 1.0; \
+                        offset: -2 -1; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_runner"; \
+                mouse_events: 0; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 0 3; \
+                    max: 99999 3; \
+                    fixed: 1 1; \
+                    align: 0.5 0.5; \
+                    rel1 { \
+                        to: "sb_hbar"; \
+                        relative: 0.0 0.5; \
+                        offset: 2 0; \
+                    } \
+                    rel2 { \
+                        to: "sb_hbar"; \
+                        relative: 1.0 0.5; \
+                        offset: -2 0; \
+                    } \
+                    image { \
+                        normal: "sb_runnerh.png"; \
+                        border: 4 4 0 0; \
+                    } \
+                    fill.smooth: 0; \
+                } \
+            } \
+            part { name: "elm.dragable.hbar"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_hbar_clip"; \
+                dragable { \
+                    x: 1 1 0; \
+                    y: 0 0 0; \
+                    confine: "sb_hbar"; \
+                } \
+                description { state: "default" 0.0; \
+                    min: 17 17; \
+                    fixed: 1 1; \
+                    aspect_preference: HORIZONTAL; \
+                    align: 0.0 1.0; \
+                    color: 0 0 0 0; \
+                    rel1 { \
+                        to_x: "sb_hbar"; \
+                        relative: 0.0 1.0; \
+                    } \
+                    rel2.to_x: "sb_hbar"; \
+                } \
+            } \
+            part { name: "elm.dragable.hbar.image"; \
+                mouse_events: 0; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "elm.dragable.hbar"; \
+                    rel2.to: "elm.dragable.hbar"; \
+                    image { \
+                        normal: "bt_sm_base2.png"; \
+                        border: 6 6 6 6; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_over1"; \
+                clip_to: "sb_hbar_clip"; \
+                mouse_events: 0; \
+                description { state: "default" 0.0; \
+                    rel1.to: "elm.dragable.hbar.image"; \
+                    rel2 { \
+                        to: "elm.dragable.hbar.image"; \
+                        relative: 1.0 0.5; \
+                    } \
+                    image { \
+                        normal: "bt_sm_hilight.png"; \
+                        border: 6 6 6 0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_over2"; \
+                clip_to: "sb_hbar_clip"; \
+                mouse_events: 0; \
+                description { state: "default" 0.0; \
+                    rel1.to: "elm.dragable.hbar.image"; \
+                    rel2.to: "elm.dragable.hbar.image"; \
+                    image { \
+                        normal: "bt_sm_shine.png"; \
+                        border: 6 6 6 0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_p1"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    color: 0 0 0 0; \
+                    fixed: 1 1; \
+                    rel1 { \
+                        to: "sb_hbar_a1"; \
+                        relative: 1.0 0.0; \
+                    } \
+                    rel2 { \
+                        to: "elm.dragable.hbar"; \
+                        relative: 0.0 1.0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_p2"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    color: 0 0 0 0; \
+                    fixed: 1 1; \
+                    rel1 { \
+                        to: "elm.dragable.hbar"; \
+                        relative: 1.0 0.0; \
+                    } \
+                    rel2 { \
+                        to: "sb_hbar_a2"; \
+                        relative: 0.0 1.0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_a1"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 17 17; \
+                    fixed: 1 1; \
+                    align: 0.0 1.0; \
+                    aspect: 1.0 1.0; \
+                    aspect_preference: VERTICAL; \
+                    color: 0 0 0 0; \
+                    rel1 { \
+                        to_x: "sb_hbar_clip"; \
+                        to_y: "elm.scrollbar.base"; \
+                        relative: 0.0 0.0; \
+                    } \
+                    rel2 { \
+                        to: "elm.scrollbar.base"; \
+                        relative: 0.0 1.0; \
+                        offset: -1 -1; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_a1_arrow"; \
+                mouse_events: 0; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "sb_hbar_a1"; \
+                    rel2.to: "sb_hbar_a1"; \
+                    image.normal: "arrow_left.png"; \
+                } \
+                description { state: "clicked" 0.0; \
+                    inherit: "default" 0.0; \
+                    rel1.offset: -1 0; \
+                    rel2.offset: -2 -1; \
+                } \
+            } \
+            part { name: "sb_hbar_a2"; \
+                type: RECT; \
+                mouse_events: 1; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    min: 17 17; \
+                    align: 1.0 1.0; \
+                    aspect: 1.0 1.0; \
+                    fixed: 1 1; \
+                    aspect_preference: VERTICAL; \
+                    color: 0 0 0 0; \
+                    rel1 { \
+                        to: "elm.scrollbar.base"; \
+                        relative: 1.0 0.0; \
+                    } \
+                    rel2 { \
+                        to: "elm.scrollbar.base"; \
+                        relative: 0.0 1.0; \
+                    } \
+                } \
+            } \
+            part { name: "sb_hbar_a2_arrow"; \
+                mouse_events: 0; \
+                clip_to: "sb_hbar_clip"; \
+                description { state: "default" 0.0; \
+                    rel1.to: "sb_hbar_a2"; \
+                    rel2.to: "sb_hbar_a2"; \
+                    image.normal: "arrow_right.png"; \
+                } \
+                description { state: "clicked" 0.0; \
+                    inherit: "default" 0.0; \
+                    rel1.offset: 1 0; \
+                    rel2.offset: 0 -1; \
+                } \
+            } \
+            part { name: "disabler"; \
+               type: RECT; \
+               description { state: "default" 0.0; \
+                  rel1.to: "clipper"; \
+                  rel2.to: "clipper"; \
+                  color: 0 0 0 0; \
+                  visible: 0; \
+               } \
+               description { state: "disabled" 0.0; \
+                  inherit: "default" 0.0; \
+                  visible: 1; \
+                  color: 128 128 128 128; \
+               } \
+            } \
+            programs { \
+                program { name: "load"; \
+                    signal: "load"; \
+                    source: ""; \
+                    script { \
+                        set_state(PART:"sb_hbar_clip", "hidden", 0.0); \
+                        set_state(PART:"sb_vbar_clip", "hidden", 0.0); \
+                        set_int(sbvis_h, 0); \
+                        set_int(sbvis_v, 0); \
+                    } \
+                } \
+                program { name: "vbar_show"; \
+                    signal: "elm,action,show,vbar"; \
+                    source: "elm"; \
+                    script { \
+                        set_state(PART:"sb_vbar_clip_master", "default", 0.0); \
+                        set_int(sbvis_v, 1); \
+                        if (get_int(sbvis_h)) \
+                            set_state(PART:"elm.scrollbar.base", "both", 0.0); \
+                        else \
+                            set_state(PART:"elm.scrollbar.base", "vertical", 0.0); \
+                        emit("do-show-vbar", ""); \
+                    } \
+                } \
+                program { name: "vbar_hide"; \
+                    signal: "elm,action,hide,vbar"; \
+                    source: "elm"; \
+                    script { \
+                        set_state(PART:"sb_vbar_clip_master", "hidden", 0.0); \
+                        set_int(sbvis_v, 0); \
+                        if (get_int(sbvis_h)) \
+                            set_state(PART:"elm.scrollbar.base", "horizontal", 0.0); \
+                        else \
+                            set_state(PART:"elm.scrollbar.base", "default", 0.0); \
+                        emit("do-hide-vbar", ""); \
+                    } \
+                } \
+                program { name: "sb_vbar_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "elm.dragable.vbar"; \
+                    action: STATE_SET "clicked" 0.0; \
+                    target: "elm.dragable.vbar"; \
+                } \
+                program { name: "sb_vbar_up"; \
+                    signal: "mouse,up,1"; \
+                    source: "elm.dragable.vbar"; \
+                    action: STATE_SET "default" 0.0; \
+                    target: "elm.dragable.vbar"; \
+                } \
+                program { name: "sb_vbar_show"; \
+                    signal: "do-show-vbar"; \
+                    source: ""; \
+                    action: STATE_SET "default" 0.0; \
+                    transition: LINEAR 0.1; \
+                    target: "sb_vbar_clip"; \
+                } \
+                program { name: "sb_vbar_hide"; \
+                    signal: "do-hide-vbar"; \
+                    source: ""; \
+                    action: STATE_SET "hidden" 0.0; \
+                    transition: LINEAR 1.0; \
+                    target: "sb_vbar_clip"; \
+                } \
+                program { name: "sb_vbar_a1_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_vbar_a1"; \
+                    action: STATE_SET "clicked" 0.0; \
+                    target: "sb_vbar_a1_arrow"; \
+                } \
+                program { name: "sb_vbar_a1_down2"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_vbar_a1"; \
+                    action: DRAG_VAL_STEP 0.0 -1.0; \
+                    target: "elm.dragable.vbar"; \
+                } \
+                program { name: "sb_vbar_a1_up"; \
+                    signal: "mouse,up,1"; \
+                    source: "sb_vbar_a1"; \
+                    action: STATE_SET "default" 0.0; \
+                    target: "sb_vbar_a1_arrow"; \
+                } \
+                program { name: "sb_vbar_a2_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_vbar_a2"; \
+                    action: STATE_SET "clicked" 0.0; \
+                    target: "sb_vbar_a2_arrow"; \
+                } \
+                program { name: "sb_vbar_a2_down2"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_vbar_a2"; \
+                    action: DRAG_VAL_STEP 0.0 1.0; \
+                    target: "elm.dragable.vbar"; \
+                } \
+                program { name: "sb_vbar_a2_up"; \
+                    signal: "mouse,up,1"; \
+                    source: "sb_vbar_a2"; \
+                    action: STATE_SET "default" 0.0; \
+                    target: "sb_vbar_a2_arrow"; \
+                } \
+                program { name: "sb_vbar_p1_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_vbar_p1"; \
+                    action: DRAG_VAL_PAGE 0.0 -1.0; \
+                    target: "elm.dragable.vbar"; \
+                } \
+                program { name: "sb_vbar_p2_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_vbar_p2"; \
+                    action: DRAG_VAL_PAGE 0.0 1.0; \
+                    target: "elm.dragable.vbar"; \
+                } \
+                program { name: "hbar_show"; \
+                    signal: "elm,action,show,hbar"; \
+                    source: "elm"; \
+                    script { \
+                        set_state(PART:"sb_hbar_clip_master", "default", 0.0); \
+                        set_int(sbvis_h, 1); \
+                        if (get_int(sbvis_v)) \
+                            set_state(PART:"elm.scrollbar.base", "both", 0.0); \
+                        else \
+                            set_state(PART:"elm.scrollbar.base", "horizontal", 0.0); \
+                        emit("do-show-hbar", ""); \
+                    } \
+                } \
+                program { name: "hbar_hide"; \
+                    signal: "elm,action,hide,hbar"; \
+                    source: "elm"; \
+                    script { \
+                        set_state(PART:"sb_hbar_clip_master", "hidden", 0.0); \
+                        set_int(sbvis_h, 0); \
+                        if (get_int(sbvis_v)) \
+                            set_state(PART:"elm.scrollbar.base", "vertical", 0.0); \
+                        else \
+                            set_state(PART:"elm.scrollbar.base", "default", 0.0); \
+                        emit("do-hide-hbar", ""); \
+                    } \
+                } \
+                program { name: "sb_hbar_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "elm.dragable.hbar"; \
+                    action: STATE_SET "clicked" 0.0; \
+                    target: "elm.dragable.hbar"; \
+                } \
+                program { name: "sb_hbar_up"; \
+                    signal: "mouse,up,1"; \
+                    source: "elm.dragable.hbar"; \
+                    action: STATE_SET "default" 0.0; \
+                    target: "elm.dragable.hbar"; \
+                } \
+                program { name: "sb_hbar_show"; \
+                    signal: "do-show-hbar"; \
+                    source: ""; \
+                    action: STATE_SET "default" 0.0; \
+                    transition: LINEAR 0.1; \
+                    target: "sb_hbar_clip"; \
+                } \
+                program { name: "sb_hbar_hide"; \
+                    signal: "do-hide-hbar"; \
+                    source: ""; \
+                    action: STATE_SET "hidden" 0.0; \
+                    transition: LINEAR 1.0; \
+                    target: "sb_hbar_clip"; \
+                } \
+                program { name: "sb_hbar_a1_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_hbar_a1"; \
+                    action: STATE_SET "clicked" 0.0; \
+                    target: "sb_hbar_a1_arrow"; \
+                } \
+                program { name: "sb_hbar_a1_down2"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_hbar_a1"; \
+                    action: DRAG_VAL_STEP -1.0 0.0; \
+                    target: "elm.dragable.hbar"; \
+                } \
+                program { name: "sb_hbar_a1_up"; \
+                    signal: "mouse,up,1"; \
+                    source: "sb_hbar_a1"; \
+                    action: STATE_SET "default" 0.0; \
+                    target: "sb_hbar_a1_arrow"; \
+                } \
+                program { name: "sb_hbar_a2_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_hbar_a2"; \
+                    action: STATE_SET "clicked" 0.0; \
+                    target: "sb_hbar_a2_arrow"; \
+                } \
+                program { name: "sb_hbar_a2_down2"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_hbar_a2"; \
+                    action: DRAG_VAL_STEP 1.0 0.0; \
+                    target: "elm.dragable.hbar"; \
+                } \
+                program { name: "sb_hbar_a2_up"; \
+                    signal: "mouse,up,1"; \
+                    source: "sb_hbar_a2"; \
+                    action: STATE_SET "default" 0.0; \
+                    target: "sb_hbar_a2_arrow"; \
+                } \
+                program { name: "sb_hbar_p1_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_hbar_p1"; \
+                    action: DRAG_VAL_PAGE -1.0 0.0; \
+                    target: "elm.dragable.hbar"; \
+                } \
+                program { name: "sb_hbar_p2_down"; \
+                    signal: "mouse,down,1"; \
+                    source: "sb_hbar_p2"; \
+                    action: DRAG_VAL_PAGE 1.0 0.0; \
+                    target: "elm.dragable.hbar"; \
+                } \
+                program { name: "disable"; \
+                    signal: "elm,state,disabled"; \
+                    source: "elm"; \
+                    action: STATE_SET "disabled" 0.0; \
+                    target: "disabler"; \
+                } \
+                program { name: "enable"; \
+                    signal: "elm,state,enabled"; \
+                    source: "elm"; \
+                    action: STATE_SET "default" 0.0; \
+                    target: "disabler"; \
+                } \
+            } \
+
+collections {
+
+    group { name: "elm/scroller/base/default";
+        alias: "elm/list/base/default";
+        alias: "elm/genlist/base/default";
+        alias: "elm/carousel/base/default";
+        alias: "elm/gengrid/base/default";
+
+        data {
+            item: "focus_highlight" "on";
+        }
+
+        images {
+            image: "shelf_inset.png" COMP;
+            image: "sl_bt2_2.png" COMP;
+        }
+
+        parts {
+            part { name: "bg";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.offset: 1 1;
+                    rel2.offset: -2 -2;
+                    color: 255 255 255 0;
+                }
+            }
+            part { name: "clipper";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.to: "bg";
+                    rel2.to: "bg";
+                }
+            }
+            part { name: "elm.swallow.content";
+                type: SWALLOW;
+                clip_to: "clipper";
+                description { state: "default" 0.0;
+                    rel2 {
+                        to_x: "sb_vbar";
+                        to_y: "sb_hbar";
+                        relative: 0.0 0.0;
+                        offset: -1 -1;
+                    }
+                }
+            }
+            part { name: "conf_over";
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    image {
+                        normal: "shelf_inset.png";
+                        border: 7 7 7 7;
+                        middle: 0;
+                    }
+                    fill.smooth: 0;
+                }
+            }
+            part { name: "focus_highlight";
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.offset: -1 -1;
+                    rel2.offset: 0 0;
+                    image {
+                        normal: "sl_bt2_2.png";
+                        border: 7 7 7 7;
+                        middle: 0;
+                    }
+                    fill.smooth: 0;
+                    color: 200 155 0 0;
+                }
+                description { state: "enabled" 0.0;
+                    inherit: "default" 0.0;
+                    color: 200 155 0 255;
+                }
+            }
+            SCROLLBARS_ADD()
+        }
+    }
+
+    group { name: "elm/scroller/entry/default";
+
+        data {
+            item: "focus_highlight" "on";
+        }
+
+        images {
+            image: "shelf_inset.png" COMP;
+            image: "sl_bt2_2.png" COMP;
+        }
+
+        parts {
+            part { name: "bg";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.offset: 1 1;
+                    rel2.offset: -2 -2;
+                    color: 255 255 255 255;
+                }
+            }
+            part { name: "clipper";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.to: "bg";
+                    rel2.to: "bg";
+                }
+            }
+            part { name: "content.clipper";
+                type: RECT;
+                mouse_events: 0;
+                clip_to: "clipper";
+                description { state: "default" 0.0;
+                    rel1 {
+                        to: "elm.swallow.icon";
+                        relative: 1.0 0.0;
+                    }
+                    rel2 {
+                        to: "elm.swallow.end";
+                        relative: 0.0 1.0;
+                    }
+                }
+            }
+            part { name: "elm.swallow.icon";
+                type: SWALLOW;
+                clip_to: "clipper";
+                description { state: "default" 0.0;
+                    fixed: 1 1;
+                    visible: 0;
+                    rel1 {
+                        to: "bg";
+                        relative: 0.0 0.0;
+                        offset: 0 0;
+                    }
+                    rel2 {
+                        to: "bg";
+                        relative: 0.0 1.0;
+                        offset: -1 -1;
+                    }
+                }
+                description { state: "visible" 0.0;
+                    inherit: "default" 0.0;
+                    visible: 1;
+                }
+            }
+            part { name: "elm.swallow.end";
+                type: SWALLOW;
+                clip_to: "clipper";
+                description { state: "default" 0.0;
+                    fixed: 1 1;
+                    visible: 0;
+                    rel1 {
+                        to: "bg";
+                        relative: 1.0 0.0;
+                        offset: 0 0;
+                    }
+                    rel2 {
+                        to_x: "elm.dragable.vbar";
+                        to_y: "elm.dragable.hbar";
+                        relative: 0.0 0.0;
+                        offset: -1 -1;
+                    }
+                }
+                description { state: "visible" 0.0;
+                    inherit: "default" 0.0;
+                    visible: 1;
+                }
+            }
+            part { name: "elm.swallow.content";
+                type: SWALLOW;
+                clip_to: "content.clipper";
+                description { state: "default" 0.0;
+                    rel1 {
+                        to: "elm.swallow.icon";
+                        relative: 1.0 0.0;
+                        offset: 4 4;
+                    }
+                    rel2 {
+                        to: "elm.swallow.end";
+                        relative: 0.0 1.0;
+                        offset: -5 -5;
+                    }
+                }
+            }
+            part { name: "conf_over";
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    image {
+                        normal: "shelf_inset.png";
+                        border: 7 7 7 7;
+                        middle: 0;
+                    }
+                    fill.smooth: 0;
+                }
+            }
+            part { name: "focus_highlight";
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.offset: -1 -1;
+                    rel2.offset: 0 0;
+                    image {
+                        normal: "sl_bt2_2.png";
+                        border: 7 7 7 7;
+                        middle: 0;
+                    }
+                    fill.smooth: 0;
+                    color: 200 155 0 0;
+                }
+                description { state: "enabled" 0.0;
+                    inherit: "default" 0.0;
+                    color: 200 155 0 255;
+                }
+            }
+            SCROLLBARS_ADD()
+        }
+        programs {
+            program { name: "icon_show";
+                signal: "elm,action,show,icon";
+                source: "elm";
+                action: STATE_SET "visible" 0.0;
+                target: "elm.swallow.icon";
+            }
+            program { name: "icon_hide";
+                signal: "elm,action,hide,icon";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                target: "elm.swallow.icon";
+            }
+            program { name: "end_show";
+                signal: "elm,action,show,end";
+                source: "elm";
+                action: STATE_SET "visible" 0.0;
+                target: "elm.swallow.end";
+            }
+            program { name: "end_hide";
+                signal: "elm,action,hide,end";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                target: "elm.swallow.end";
+            }
+            program { name: "highlight_show";
+                signal: "elm,action,focus_highlight,show";
+                source: "elm";
+                action: STATE_SET "enabled" 0.0;
+                transition: ACCELERATE 0.3;
+                target: "focus_highlight";
+                target: "conf_over";
+            }
+            program { name: "highlight_hide";
+                signal: "elm,action,focus_highlight,hide";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                transition: DECELERATE 0.3;
+                target: "focus_highlight";
+                target: "conf_over";
+            }
+        }
+    }
+
+    group { name: "elm/photocam/base/default";
+
+        images {
+            image: "shelf_inset.png" COMP;
+            image: "busy-1.png" COMP;
+            image: "busy-2.png" COMP;
+            image: "busy-3.png" COMP;
+            image: "busy-4.png" COMP;
+            image: "busy-5.png" COMP;
+            image: "busy-6.png" COMP;
+            image: "busy-7.png" COMP;
+            image: "busy-8.png" COMP;
+            image: "busy-9.png" COMP;
+        }
+        parts {
+            part { name: "bg";
+                type: RECT;
+                description { state: "default" 0.0;
+                    rel1.offset: 1 1;
+                    rel2.offset: -2 -2;
+                    color: 255 255 255 0;
+                }
+            }
+            part { name: "clipper";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.to: "bg";
+                    rel2.to: "bg";
+                }
+            }
+            part { name: "elm.swallow.content";
+                clip_to: "clipper";
+                type: SWALLOW;
+                description { state: "default" 0.0;
+                    rel1.offset: 1 1;
+                    rel2.offset: -2 -2;
+                }
+            }
+            part { name: "busy_clip";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    visible: 0;
+                    color: 255 255 255 0;
+                }
+                description { state: "active" 0.0;
+                    visible: 1;
+                    color: 255 255 255 255;
+                }
+            }
+            part { name: "busy";
+                clip_to: "busy_clip";
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    fixed: 1 1;
+                    min: 32 32;
+                    aspect: 1.0 1.0;
+                    align: 1.0 1.0;
+                    aspect_preference: BOTH;
+                    rel1 {
+                        relative: 0.9 0.9;
+                        offset:   -9 -9;
+                    }
+                    rel2 {
+                        relative: 0.9 0.9;
+                        offset:   -9 -9;
+                    }
+                    image {
+                        normal: "busy-9.png";
+                        tween:  "busy-1.png";
+                        tween:  "busy-2.png";
+                        tween:  "busy-3.png";
+                        tween:  "busy-4.png";
+                        tween:  "busy-5.png";
+                        tween:  "busy-6.png";
+                        tween:  "busy-7.png";
+                        tween:  "busy-8.png";
+                    }
+                }
+            }
+            part { name: "conf_over";
+                mouse_events:  0;
+                description { state: "default" 0.0;
+                    rel1.offset: 0 0;
+                    rel2.offset: -1 -1;
+                    image {
+                        normal: "shelf_inset.png";
+                        border: 7 7 7 7;
+                        middle: 0;
+                    }
+                    fill.smooth : 0;
+                }
+            }
+            SCROLLBARS_ADD()
+        }
+        programs {
+            program { name: "go1";
+                signal: "elm,state,busy,start";
+                source: "elm";
+                action: STATE_SET "active" 0.0;
+                transition: SINUSOIDAL 1.0;
+                target:  "busy_clip";
+            }
+            program { name: "go2";
+                signal: "elm,state,busy,start";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                transition: LINEAR 0.5;
+                target: "busy";
+                after:  "go2";
+            }
+            program { name: "stop1";
+                signal: "elm,state,busy,stop";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                transition: SINUSOIDAL 1.0;
+                target: "busy_clip";
+                after: "stop2";
+            }
+            program { name: "stop2";
+                action: ACTION_STOP;
+                target: "go2";
+            }
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    group { name: "elm/map/base/default";
+        images {
+            image: "shelf_inset.png" COMP;
+            image: "busy-1.png" COMP;
+            image: "busy-2.png" COMP;
+            image: "busy-3.png" COMP;
+            image: "busy-4.png" COMP;
+            image: "busy-5.png" COMP;
+            image: "busy-6.png" COMP;
+            image: "busy-7.png" COMP;
+            image: "busy-8.png" COMP;
+            image: "busy-9.png" COMP;
+        }
+        parts {
+            part { name: "bg";
+                type: RECT;
+                description { state: "default" 0.0;
+                    rel1.offset: 1 1;
+                    rel2.offset: -2 -2;
+                    color: 255 255 255 0;
+                }
+            }
+            part { name: "clipper";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.to: "bg";
+                    rel2.to: "bg";
+                }
+            }
+            part { name: "elm.swallow.content";
+                clip_to: "clipper";
+                type: SWALLOW;
+                description { state: "default" 0.0;
+                    rel1.offset: 1 1;
+                    rel2.offset: -2 -2;
+                }
+            }
+            part { name: "busy_clip";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    visible: 0;
+                    color: 255 255 255 0;
+                }
+                description { state: "active" 0.0;
+                    visible: 1;
+                    color: 255 255 255 255;
+                }
+            }
+            part { name: "busy";
+                clip_to: "busy_clip";
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    fixed: 1 1;
+                    min: 32 32;
+                    aspect: 1.0 1.0;
+                    align: 1.0 1.0;
+                    aspect_preference: BOTH;
+                    rel1 {
+                        relative: 0.9 0.9;
+                        offset:   -9 -9;
+                    }
+                    rel2 {
+                        relative: 0.9 0.9;
+                        offset:   -9 -9;
+                    }
+                    image {
+                        normal: "busy-9.png";
+                        tween:  "busy-1.png";
+                        tween:  "busy-2.png";
+                        tween:  "busy-3.png";
+                        tween:  "busy-4.png";
+                        tween:  "busy-5.png";
+                        tween:  "busy-6.png";
+                        tween:  "busy-7.png";
+                        tween:  "busy-8.png";
+                    }
+                }
+            }
+            part { name: "conf_over";
+                mouse_events:  0;
+                description { state: "default" 0.0;
+                    rel1.offset: 0 0;
+                    rel2.offset: -1 -1;
+                    image {
+                        normal: "shelf_inset.png";
+                        border: 7 7 7 7;
+                        middle: 0;
+                    }
+                    fill.smooth : 0;
+                }
+            }
+            SCROLLBARS_ADD()
+        }
+        programs {
+            program { name: "go1";
+                signal: "elm,state,busy,start";
+                source: "elm";
+                action: STATE_SET "active" 0.0;
+                transition: SINUSOIDAL 1.0;
+                target:  "busy_clip";
+            }
+            program { name: "go2";
+                signal: "elm,state,busy,start";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                transition: LINEAR 0.5;
+                target: "busy";
+                after:  "go2";
+            }
+            program { name: "stop1";
+                signal: "elm,state,busy,stop";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                transition: SINUSOIDAL 1.0;
+                target: "busy_clip";
+                after: "stop2";
+            }
+            program { name: "stop2";
+                action: ACTION_STOP;
+                target: "go2";
+            }
+        }
+    }
+
+    group { name: "elm/list/base/hoverlist";
+        data {
+            item: "focus_highlight" "on";
+        }
+        images {
+            image: "sl_bt2_2.png" COMP;
+        }
+        parts {
+            part { name: "bg";
+                type: RECT;
+                description { state: "default" 0.0;
+                    rel1.offset: 2 2;
+                    rel2.offset: -3 -3;
+                    color: 255 255 255 0;
+                }
+            }
+            part { name: "clipper";
+                type: RECT;
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1 {
+                        to: "bg";
+                        offset: 2 2;
+                    }
+                    rel2 {
+                        to: "bg";
+                        offset: -3 -3;
+                    }
+                }
+            }
+            part { name: "elm.swallow.content";
+                clip_to: "clipper";
+                type: SWALLOW;
+                description { state: "default" 0.0;
+                    rel1 {
+                        to: "bg";
+                        offset: 2 2;
+                    }
+                    rel2 {
+                        to: "bg";
+                        offset: -3 -3;
+                    }
+                }
+            }
+            part { name: "focus_highlight";
+                mouse_events: 0;
+                description { state: "default" 0.0;
+                    rel1.offset: -1 -1;
+                    rel2.offset: 0 0;
+                    image {
+                        normal: "sl_bt2_2.png";
+                        border: 7 7 7 7;
+                        middle: 0;
+                    }
+                    fill.smooth : 0;
+                    color: 200 155 0 0;
+                }
+                description { state: "enabled" 0.0;
+                    inherit: "default" 0.0;
+                    color: 200 155 0 255;
+                }
+            }
+            SCROLLBARS_ADD()
+        }
+        programs {
+            program { name: "highlight_show";
+                signal: "elm,action,focus_highlight,show";
+                source: "elm";
+                action: STATE_SET "enabled" 0.0;
+                transition: ACCELERATE 0.3;
+                target: "focus_highlight";
+            }
+            program { name: "highlight_hide";
+                signal: "elm,action,focus_highlight,hide";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                transition: DECELERATE 0.3;
+                target: "focus_highlight";
+            }
+        }
+    }
+}
diff --git a/data/themes/default.edc b/data/themes/default.edc
new file mode 100644 (file)
index 0000000..834e7eb
--- /dev/null
@@ -0,0 +1,36110 @@
+// LICENSE NOTE:
+// This file (and only this one) is licenses under public-domain. The reason
+// is that this is meant to serve as a template for making your own themes and
+// Elementary's LGPL license is not intended to follow. The images used do come
+// under LGPL, but this file specifically for the structure of your theme is
+// public-domain. This means you can take, use, re-license and otherwise
+// have zero restrictions on using this file as a base for your theme.
+
+externals.external: "elm";
+
+collections {
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/focus_highlight/top/default";
+      images {
+         image: "emo-unhappy.png" COMP;
+      }
+
+      data {
+         item: "animate" "on";
+      }
+
+      script {
+         public s_x, s_y, s_w, s_h; /* source */
+         public difx, dify, difw, difh;
+         public rot_dir;
+
+         public animator1(val, Float:pos) {
+            new x, y, w, h, dx, dy, dw, dh, Float:rot;
+
+            dx = round(float_mul(float(get_int(difx)), pos));
+            x = get_int(s_x) + dx;
+            dy = round(float_mul(float(get_int(dify)), pos));
+            y = get_int(s_y) + dy;
+            dw = round(float_mul(float(get_int(difw)), pos));
+            w = get_int(s_w) + dw;
+            dy = round(float_mul(float(get_int(difh)), pos));
+            h = get_int(s_h) + dh;
+
+            update_offset(x, y, w, h);
+
+            rot = 360.0 * pos * float(get_int(rot_dir));
+            set_state_val(PART:"shine", STATE_MAP_ROT_Z, rot);
+
+            if (pos >= 1.0) {
+               emit("elm,action,focus,anim,end", "");
+               set_state(PART:"shine", "default", 0.0);
+            }
+         }
+
+         public update_offset(x, y, w, h) {
+            new x1, y1, x2, y2;
+            x1 = x + w - 15;
+            y1 = y - 15;
+            x2 = x + w + 14;
+            y2 = y + 14;
+            set_state_val(PART:"shine", STATE_REL1_OFFSET, x1, y1);
+            set_state_val(PART:"shine", STATE_REL2_OFFSET, x2, y2);
+         }
+
+         public message(Msg_Type:type, id, ...) {
+            if ((type == MSG_INT_SET) && (id == 1)) {
+               new x1, y1, w1, h1;
+               new x2, y2, w2, h2;
+               new px1, px2, py1, py2;
+               new rd;
+
+               x1 = getarg(2);
+               y1 = getarg(3);
+               w1 = getarg(4);
+               h1 = getarg(5);
+               x2 = getarg(6);
+               y2 = getarg(7);
+               w2 = getarg(8);
+               h2 = getarg(9);
+
+               set_int(s_x, x1);
+               set_int(s_y, y1);
+               set_int(s_w, w1);
+               set_int(s_h, h1);
+               set_int(difx, x2 - x1);
+               set_int(dify, y2 - y1);
+               set_int(difw, w2 - w1);
+               set_int(difh, h2 - h1);
+
+               px1 = x1 + w1;
+               px2 = x2 + w2;
+               py1 = y1 + h1;
+               py2 = y2 + h2;
+               if (px2 > px1) {
+                  rd = 1;
+               } else if (px1 > px2) {
+                  rd = -1;
+               } else {
+                  if (py2 > py1) {
+                     rd = 1;
+                  } else {
+                     rd = -1;
+                  }
+               }
+               set_int(rot_dir, rd);
+
+               custom_state(PART:"shine", "default", 0.0);
+               set_state_val(PART:"shine", STATE_REL1, 0.0, 0.0);
+               set_state_val(PART:"shine", STATE_REL2, 0.0, 0.0);
+               set_state_val(PART:"shine", STATE_MAP_ON, 1);
+               set_state_val(PART:"shine", STATE_MAP_ROT_Z, 0.0);
+               update_offset(x1, y1, w1, h1);
+               set_state(PART:"shine", "custom", 0.0);
+
+               anim(0.2, "animator1", 1);
+            }
+         }
+      }
+
+      parts {
+         part { name: "base";
+            type: RECT;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 1.0 1.0;
+               visible: 0;
+            }
+         }
+         part { name: "shine";
+            type: IMAGE;
+            mouse_events: 1;
+            repeat_events: 1;
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               image {
+                  normal: "emo-unhappy.png";
+               }
+               rel1.to: "base";
+               rel1.relative: 1.0 0.0;
+               rel1.offset: -15 -15;
+               rel2.to: "base";
+               rel2.relative: 1.0 0.0;
+               rel2.offset: 14 14;
+            }
+            description { state: "disabled" 0.0;
+               inherit:  "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+
+         program { name: "show";
+            signal: "elm,action,focus,show";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "hide";
+            target: "hide_start";
+            target: "hide_end";
+            after: "show_start";
+         }
+         program { name: "show_start";
+            action:  STATE_SET "default" 0.0;
+            transition: LINEAR 0.2;
+            target: "shine";
+            after: "show_end";
+         }
+         program { name: "show_end";
+            action: SIGNAL_EMIT "elm,action,focus,show,end" "";
+         }
+         program { name: "hide";
+            signal: "elm,action,focus,hide";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "show";
+            target: "show_start";
+            target: "show_end";
+            after: "hide_start";
+         }
+         program { name: "hide_start";
+            action:  STATE_SET "disabled" 0.0;
+            transition: LINEAR 0.2;
+            target: "shine";
+            after: "hide_end";
+         }
+         program { name: "hide_end";
+            action: SIGNAL_EMIT "elm,action,focus,hide,end" "";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/focus_highlight/bottom/default";
+      parts {
+         part { name: "shine";
+            type: RECT;
+            mouse_events: 1;
+            repeat_events: 1;
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               color: 0 255 0 50;
+               rel1.offset: 0 0;
+               rel2.offset: 0 0;
+            }
+            description { state: "disabled" 0.0;
+               inherit:  "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+
+         program { name: "show";
+            signal: "elm,action,focus,show";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "hide";
+            target: "hide_start";
+            target: "hide_end";
+            after: "show_start";
+         }
+         program { name: "show_start";
+            action:  STATE_SET "default" 0.0;
+            transition: LINEAR 0.2;
+            target: "shine";
+            after: "show_end";
+         }
+         program { name: "show_end";
+            action: SIGNAL_EMIT "elm,action,focus,show,end" "";
+         }
+         program { name: "hide";
+            signal: "elm,action,focus,hide";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "show";
+            target: "show_start";
+            target: "show_end";
+            after: "hide_start";
+         }
+         program { name: "hide_start";
+            action:  STATE_SET "disabled" 0.0;
+            transition: LINEAR 0.2;
+            target: "shine";
+            after: "hide_end";
+         }
+         program { name: "hide_end";
+            action: SIGNAL_EMIT "elm,action,focus,hide,end" "";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/bg/base/default";
+      images {
+         image: "dia_grad.png" COMP;
+        image: "dia_topshad.png" COMP;
+        image: "dia_botshad.png" COMP;
+      }
+      parts {
+         part { name: "base";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "dia_grad.png";
+              fill {
+                 smooth: 0;
+                 size {
+                    relative: 0.0 1.0;
+                    offset: 64 0;
+                 }
+              }
+           }
+        }
+        part { name: "elm.swallow.rectangle";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+           }
+        }
+        part { name: "elm.swallow.background";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+           }
+        }
+        part { name: "shadow";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              rel2.relative: 1.0 0.0;
+              rel2.offset: -1 31;
+              image.normal: "dia_topshad.png";
+              fill {
+                 smooth: 0;
+                 size {
+                    relative: 0.0 1.0;
+                    offset: 64 0;
+                 }
+              }
+           }
+        }
+        part { name: "shadow2";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              rel1.relative: 0.0 1.0;
+              rel1.offset: 0 -9;
+              image.normal: "dia_botshad.png";
+              fill {
+                 smooth: 0;
+                 size {
+                    relative: 0.0 1.0;
+                    offset: 64 0;
+                 }
+              }
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+           }
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/scroller/base/default";
+
+      alias: "elm/list/base/default";
+      alias: "elm/genlist/base/default";
+      alias: "elm/carousel/base/default";
+      alias: "elm/gengrid/base/default";
+
+      data {
+         item: "focus_highlight" "on";
+      }
+
+      script {
+        public sbvis_v, sbvis_h, sbalways_v, sbalways_h, sbvis_timer;
+        public timer0(val) {
+           new v;
+           v = get_int(sbvis_v);
+           if (v) {
+               v = get_int(sbalways_v);
+               if (!v) {
+                  emit("do-hide-vbar", "");
+                  set_int(sbvis_v, 0);
+               }
+           }
+           v = get_int(sbvis_h);
+           if (v) {
+               v = get_int(sbalways_h);
+               if (!v) {
+                  emit("do-hide-hbar", "");
+                  set_int(sbvis_h, 0);
+               }
+           }
+           set_int(sbvis_timer, 0);
+           return 0;
+        }
+      }
+      images {
+        image: "shelf_inset.png" COMP;
+        image: "bt_sm_base2.png" COMP;
+        image: "bt_sm_shine.png" COMP;
+        image: "bt_sm_hilight.png" COMP;
+         image: "sl_bt2_2.png" COMP;
+      }
+      parts {
+         part { name: "bg";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel1.offset: 2 2;
+              rel2.offset: -3 -3;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "clipper";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "bg";
+              rel2.to: "bg";
+              rel1.offset: 2 2;
+              rel2.offset: -3 -3;
+           }
+        }
+        part { name: "elm.swallow.content";
+           clip_to: "clipper";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.to: "bg";
+              rel2.to: "bg";
+              rel1.offset: 2 2;
+              rel2.offset: -3 -3;
+           }
+        }
+        part { name: "conf_over";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              rel1.to: "bg";
+              rel2.to: "bg";
+              image {
+                 normal: "shelf_inset.png";
+                 border: 7 7 7 7;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+            description { state: "enabled" 0.0;
+               inherit: "default" 0.0;
+               color: 200 155 0 255;
+            }
+         }
+         part { name: "focus_highlight";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.offset: -1 -1;
+               rel2.offset: 0 0;
+               image {
+                  normal: "sl_bt2_2.png";
+                  border: 7 7 7 7;
+                  middle: 0;
+               }
+               fill.smooth : 0;
+               color: 200 155 0 0;
+            }
+            description { state: "enabled" 0.0;
+               inherit: "default" 0.0;
+               color: 200 155 0 255;
+            }
+         }
+        part { name: "sb_vbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_vbar_clip";
+            clip_to: "sb_vbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_vbar";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              visible: 0;
+              min: 10 17;
+              align: 1.0 0.0;
+              rel1 {
+                 relative: 1.0 0.0;
+                 offset:   0 2;
+                 to_y:     "elm.swallow.content";
+                  to_x:     "elm.swallow.content";
+              }
+              rel2 {
+                 relative: 1.0 0.0;
+                 offset:   -1 -1;
+                 to_y:     "sb_hbar";
+                  to_x:     "elm.swallow.content";
+              }
+           }
+        }
+        part { name: "elm.dragable.vbar";
+           clip_to: "sb_vbar_clip";
+           mouse_events: 0;
+           dragable {
+              x: 0 0 0;
+              y: 1 1 0;
+              confine: "sb_vbar";
+           }
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              min: 10 17;
+               max: 10 99999;
+              rel1 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_vbar";
+              }
+              rel2 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_vbar";
+              }
+              image {
+                 normal: "bt_sm_base2.png";
+                 border: 6 6 6 6;
+                  middle: SOLID;
+              }
+           }
+        }
+        part { name: "sb_vbar_over1";
+           clip_to: "sb_vbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.vbar";
+              rel2.relative: 1.0 0.5;
+              rel2.to: "elm.dragable.vbar";
+              image {
+                 normal: "bt_sm_hilight.png";
+                 border: 6 6 6 0;
+              }
+           }
+        }
+        part { name: "sb_vbar_over2";
+           clip_to: "sb_vbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.vbar";
+              rel2.to: "elm.dragable.vbar";
+              image {
+                 normal: "bt_sm_shine.png";
+                 border: 6 6 6 0;
+              }
+           }
+        }
+
+        part { name: "sb_hbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_hbar_clip";
+            clip_to: "sb_hbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_hbar";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              visible: 0;
+              min: 17 10;
+              align: 0.0 1.0;
+              rel1 {
+                 relative: 0.0 1.0;
+                 offset:   2 0;
+                 to_x:     "elm.swallow.content";
+                  to_y:     "elm.swallow.content";
+              }
+              rel2 {
+                 relative: 0.0 1.0;
+                 offset:   -1 -1;
+                 to_x:     "sb_vbar";
+                  to_y:     "elm.swallow.content";
+              }
+           }
+        }
+        part { name: "elm.dragable.hbar";
+           clip_to: "sb_hbar_clip";
+           mouse_events: 0;
+           dragable {
+              x: 1 1 0;
+              y: 0 0 0;
+              confine: "sb_hbar";
+           }
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              min: 17 10;
+               max: 99999 10;
+              rel1 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_hbar";
+              }
+              rel2 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_hbar";
+              }
+              image {
+                 normal: "bt_sm_base2.png";
+                 border: 4 4 4 4;
+                  middle: SOLID;
+              }
+           }
+        }
+        part { name: "sb_hbar_over1";
+           clip_to: "sb_hbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.hbar";
+              rel2.relative: 1.0 0.5;
+              rel2.to: "elm.dragable.hbar";
+              image {
+                 normal: "bt_sm_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "sb_hbar_over2";
+           clip_to: "sb_hbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.hbar";
+              rel2.to: "elm.dragable.hbar";
+              image {
+                 normal: "bt_sm_shine.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+               rel1.to: "clipper";
+               rel2.to: "clipper";
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+               color: 128 128 128 128;
+           }
+        }
+      }
+      programs {
+        program { name: "load";
+           signal: "load";
+           source: "";
+           script {
+              set_state(PART:"sb_hbar_clip", "hidden", 0.0);
+              set_state(PART:"sb_vbar_clip", "hidden", 0.0);
+              set_int(sbvis_h, 0);
+              set_int(sbvis_v, 0);
+              set_int(sbalways_v, 0);
+              set_int(sbalways_h, 0);
+              set_int(sbvis_timer, 0);
+           }
+        }
+
+        program { name: "vbar_show";
+           signal: "elm,action,show,vbar";
+           source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "sb_vbar_clip_master";
+        }
+        program { name: "vbar_hide";
+           signal: "elm,action,hide,vbar";
+           source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "sb_vbar_clip_master";
+        }
+        program { name: "vbar_show_always";
+           signal: "elm,action,show_always,vbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbvis_v);
+               v |= get_int(sbalways_v);
+               if (!v) {
+                  set_int(sbalways_v, 1);
+                  emit("do-show-vbar", "");
+                  set_int(sbvis_v, 1);
+               }
+            }
+        }
+        program { name: "vbar_show_notalways";
+           signal: "elm,action,show_notalways,vbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbalways_v);
+               if (v) {
+                  set_int(sbalways_v, 0);
+                  v = get_int(sbvis_v);
+                  if (!v) {
+                     emit("do-hide-vbar", "");
+                     set_int(sbvis_v, 0);
+                  }
+               }
+            }
+        }
+        program { name: "sb_vbar_show";
+           signal: "do-show-vbar";
+           source: "";
+           action:  STATE_SET "default" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_vbar_clip";
+        }
+        program { name: "sb_vbar_hide";
+           signal: "do-hide-vbar";
+           source: "";
+           action:  STATE_SET "hidden" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_vbar_clip";
+        }
+
+        program { name: "hbar_show";
+           signal: "elm,action,show,hbar";
+           source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "sb_hbar_clip_master";
+        }
+        program { name: "hbar_hide";
+           signal: "elm,action,hide,hbar";
+           source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "sb_hbar_clip_master";
+        }
+        program { name: "hbar_show_always";
+           signal: "elm,action,show_always,hbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbvis_h);
+               v |= get_int(sbalways_h);
+               if (!v) {
+                  set_int(sbalways_h, 1);
+                  emit("do-show-hbar", "");
+                  set_int(sbvis_h, 1);
+               }
+            }
+        }
+        program { name: "hbar_show_notalways";
+           signal: "elm,action,show_notalways,hbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbalways_h);
+               if (v) {
+                  set_int(sbalways_h, 0);
+                  v = get_int(sbvis_h);
+                  if (!v) {
+                     emit("do-hide-hbar", "");
+                     set_int(sbvis_h, 0);
+                  }
+               }
+            }
+        }
+        program { name: "sb_hbar_show";
+           signal: "do-show-hbar";
+           source: "";
+           action:  STATE_SET "default" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_hbar_clip";
+        }
+        program { name: "sb_hbar_hide";
+           signal: "do-hide-hbar";
+           source: "";
+           action:  STATE_SET "hidden" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_hbar_clip";
+        }
+
+        program { name: "scroll";
+           signal: "elm,action,scroll";
+           source: "elm";
+           script {
+              new v;
+              v = get_int(sbvis_v);
+               v |= get_int(sbalways_v);
+              if (!v) {
+                  emit("do-show-vbar", "");
+                  set_int(sbvis_v, 1);
+              }
+              v = get_int(sbvis_h);
+               v |= get_int(sbalways_h);
+              if (!v) {
+                  emit("do-show-hbar", "");
+                  set_int(sbvis_h, 1);
+              }
+              v = get_int(sbvis_timer);
+              if (v > 0) cancel_timer(v);
+              v = timer(1.0, "timer0", 0);
+              set_int(sbvis_timer, v);
+           }
+        }
+
+         program { name: "highlight_show";
+            signal: "elm,action,focus_highlight,show";
+            source: "elm";
+            action: STATE_SET "enabled" 0.0;
+            transition: ACCELERATE 0.3;
+            target: "focus_highlight";
+            target: "conf_over";
+         }
+         program { name: "highlight_hide";
+            signal: "elm,action,focus_highlight,hide";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.3;
+            target: "focus_highlight";
+            target: "conf_over";
+         }
+        program { name: "disable";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "disabler";
+         }
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "disabler";
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/scroller/entry/default";
+
+      data {
+         item: "focus_highlight" "on";
+      }
+
+      script {
+        public sbvis_v, sbvis_h, sbalways_v, sbalways_h, sbvis_timer;
+        public timer0(val) {
+           new v;
+           v = get_int(sbvis_v);
+           if (v) {
+               v = get_int(sbalways_v);
+               if (!v) {
+                  emit("do-hide-vbar", "");
+                  set_int(sbvis_v, 0);
+               }
+           }
+           v = get_int(sbvis_h);
+           if (v) {
+               v = get_int(sbalways_h);
+               if (!v) {
+                  emit("do-hide-hbar", "");
+                  set_int(sbvis_h, 0);
+               }
+           }
+           set_int(sbvis_timer, 0);
+           return 0;
+        }
+      }
+      images {
+        image: "shelf_inset.png" COMP;
+        image: "bt_sm_base2.png" COMP;
+        image: "bt_sm_shine.png" COMP;
+        image: "bt_sm_hilight.png" COMP;
+         image: "sl_bt2_2.png" COMP;
+      }
+      parts {
+         part { name: "bg";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel1.offset: 2 2;
+              rel2.offset: -3 -3;
+           }
+        }
+        part { name: "clipper";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "bg";
+              rel2.to: "bg";
+              rel1.offset: 2 2;
+              rel2.offset: -3 -3;
+           }
+        }
+        part { name: "contentclipper";
+           type: RECT;
+           mouse_events: 0;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.icon";
+              rel1.relative: 1.0 0.0;
+              rel2.to: "elm.swallow.end";
+              rel2.relative: 0.0 1.0;
+           }
+        }
+        part { name: "elm.swallow.icon";
+           type: SWALLOW;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              rel1 {
+                 to: "bg";
+                 relative: 0.0 0.0;
+                 offset: 0 0;
+              }
+              rel2 {
+                 to: "bg";
+                 relative: 0.0 1.0;
+                 offset: -1 -1;
+              }
+              visible: 0;
+           }
+           description { state: "visible" 0.0;
+              fixed: 1 1;
+              align: 0.0 1.0;
+              rel1 {
+                 to: "bg";
+                 relative: 0.0 0.0;
+                 offset: 0 0;
+              }
+              rel2 {
+                 to: "bg";
+                 relative: 0.0 1.0;
+                 offset: -1 -1;
+              }
+              visible: 1;
+           }
+        }
+        part { name: "elm.swallow.end";
+           type: SWALLOW;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              rel1 {
+                 to: "bg";
+                 relative: 1.0 0.0;
+                 offset: 0 0;
+              }
+              rel2 {
+                 to: "bg";
+                 relative: 1.0 1.0;
+                 offset: -1 -1;
+              }
+              visible: 0;
+           }
+           description { state: "visible" 0.0;
+              fixed: 1 1;
+              align: 1.0 1.0;
+              rel1 {
+                 to: "bg";
+                 relative: 1.0 0.0;
+                 offset: 0 0;
+              }
+              rel2 {
+                 to: "bg";
+                 relative: 1.0 1.0;
+                 offset: -1 -1;
+              }
+              visible: 1;
+           }
+        }
+        part { name: "elm.swallow.content";
+           clip_to: "contentclipper";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1 {
+               to: "elm.swallow.icon";
+               relative: 1.0 0.0;
+               offset: 4 4;
+              }
+              rel2 {
+               to: "elm.swallow.end";
+               relative: 0.0 1.0;
+               offset: -5 -5;
+              }
+           }
+        }
+        part { name: "conf_over";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              rel1.to: "bg";
+              rel2.to: "bg";
+              image {
+                 normal: "shelf_inset.png";
+                 border: 7 7 7 7;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+            description { state: "enabled" 0.0;
+               inherit: "default" 0.0;
+               color: 200 155 0 255;
+            }
+         }
+         part { name: "focus_highlight";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.offset: -1 -1;
+               rel2.offset: 0 0;
+               image {
+                  normal: "sl_bt2_2.png";
+                  border: 7 7 7 7;
+                  middle: 0;
+               }
+               fill.smooth : 0;
+               color: 200 155 0 0;
+            }
+            description { state: "enabled" 0.0;
+               inherit: "default" 0.0;
+               color: 200 155 0 255;
+            }
+        }
+        part { name: "sb_vbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_vbar_clip";
+            clip_to: "sb_vbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_vbar";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              visible: 0;
+              min: 10 17;
+              align: 1.0 0.0;
+              rel1 {
+                 relative: 0.0 0.0;
+                 offset:   -2 2;
+                 to_y:     "elm.swallow.content";
+                 to_x:     "elm.swallow.end";
+              }
+              rel2 {
+                 relative: 0.0 0.0;
+                 offset:   -2 -1;
+                 to_y:     "sb_hbar";
+                 to_x:     "elm.swallow.end";
+              }
+           }
+        }
+        part { name: "elm.dragable.vbar";
+           clip_to: "sb_vbar_clip";
+           mouse_events: 0;
+           dragable {
+              x: 0 0 0;
+              y: 1 1 0;
+              confine: "sb_vbar";
+           }
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              min: 10 17;
+               max: 10 99999;
+              rel1 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_vbar";
+              }
+              rel2 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_vbar";
+              }
+              image {
+                 normal: "bt_sm_base2.png";
+                 border: 6 6 6 6;
+                  middle: SOLID;
+              }
+           }
+        }
+        part { name: "sb_vbar_over1";
+           clip_to: "sb_vbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.vbar";
+              rel2.relative: 1.0 0.5;
+              rel2.to: "elm.dragable.vbar";
+              image {
+                 normal: "bt_sm_hilight.png";
+                 border: 6 6 6 0;
+              }
+           }
+        }
+        part { name: "sb_vbar_over2";
+           clip_to: "sb_vbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.vbar";
+              rel2.to: "elm.dragable.vbar";
+              image {
+                 normal: "bt_sm_shine.png";
+                 border: 6 6 6 0;
+              }
+           }
+        }
+
+        part { name: "sb_hbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_hbar_clip";
+            clip_to: "sb_hbar_clip_master";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              visible: 0;
+              color: 255 255 255 0;
+           }
+        }
+        part { name: "sb_hbar";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              visible: 0;
+              min: 17 10;
+              align: 0.0 1.0;
+              rel1 {
+                 relative: 0.0 1.0;
+                 offset:   2 0;
+                 to_x:     "elm.swallow.content";
+                  to_y:     "elm.swallow.content";
+              }
+              rel2 {
+                 relative: 0.0 1.0;
+                 offset:   -1 -1;
+                 to_x:     "sb_vbar";
+                  to_y:     "elm.swallow.content";
+              }
+           }
+        }
+        part { name: "elm.dragable.hbar";
+           clip_to: "sb_hbar_clip";
+           mouse_events: 0;
+           dragable {
+              x: 1 1 0;
+              y: 0 0 0;
+              confine: "sb_hbar";
+           }
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              min: 17 10;
+               max: 99999 10;
+              rel1 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_hbar";
+              }
+              rel2 {
+                 relative: 0.5  0.5;
+                 offset:   0    0;
+                 to: "sb_hbar";
+              }
+              image {
+                 normal: "bt_sm_base2.png";
+                 border: 4 4 4 4;
+                  middle: SOLID;
+              }
+           }
+        }
+        part { name: "sb_hbar_over1";
+           clip_to: "sb_hbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.hbar";
+              rel2.relative: 1.0 0.5;
+              rel2.to: "elm.dragable.hbar";
+              image {
+                 normal: "bt_sm_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "sb_hbar_over2";
+           clip_to: "sb_hbar_clip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "elm.dragable.hbar";
+              rel2.to: "elm.dragable.hbar";
+              image {
+                 normal: "bt_sm_shine.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+      }
+      programs {
+        program { name: "load";
+           signal: "load";
+           source: "";
+           script {
+              set_state(PART:"sb_hbar_clip", "hidden", 0.0);
+              set_state(PART:"sb_vbar_clip", "hidden", 0.0);
+              set_int(sbvis_h, 0);
+              set_int(sbvis_v, 0);
+              set_int(sbalways_v, 0);
+              set_int(sbalways_h, 0);
+              set_int(sbvis_timer, 0);
+           }
+        }
+        program { name: "icon_show";
+           signal: "elm,action,show,icon";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           target: "elm.swallow.icon";
+        }
+        program { name: "icon_hide";
+           signal: "elm,action,hide,icon";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "elm.swallow.icon";
+        }
+        program { name: "end_show";
+           signal: "elm,action,show,end";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           target: "elm.swallow.end";
+        }
+        program { name: "end_hide";
+           signal: "elm,action,hide,end";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "elm.swallow.end";
+        }
+        program { name: "vbar_show";
+           signal: "elm,action,show,vbar";
+           source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "sb_vbar_clip_master";
+        }
+        program { name: "vbar_hide";
+           signal: "elm,action,hide,vbar";
+           source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "sb_vbar_clip_master";
+        }
+        program { name: "vbar_show_always";
+           signal: "elm,action,show_always,vbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbvis_v);
+               v |= get_int(sbalways_v);
+               if (!v) {
+                  set_int(sbalways_v, 1);
+                  emit("do-show-vbar", "");
+                  set_int(sbvis_v, 1);
+               }
+            }
+        }
+        program { name: "vbar_show_notalways";
+           signal: "elm,action,show_notalways,vbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbalways_v);
+               if (v) {
+                  set_int(sbalways_v, 0);
+                  v = get_int(sbvis_v);
+                  if (!v) {
+                     emit("do-hide-vbar", "");
+                     set_int(sbvis_v, 0);
+                  }
+               }
+            }
+        }
+        program { name: "sb_vbar_show";
+           signal: "do-show-vbar";
+           source: "";
+           action:  STATE_SET "default" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_vbar_clip";
+        }
+        program { name: "sb_vbar_hide";
+           signal: "do-hide-vbar";
+           source: "";
+           action:  STATE_SET "hidden" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_vbar_clip";
+        }
+
+        program { name: "hbar_show";
+           signal: "elm,action,show,hbar";
+           source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "sb_hbar_clip_master";
+        }
+        program { name: "hbar_hide";
+           signal: "elm,action,hide,hbar";
+           source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "sb_hbar_clip_master";
+        }
+        program { name: "hbar_show_always";
+           signal: "elm,action,show_always,hbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbvis_h);
+               v |= get_int(sbalways_h);
+               if (!v) {
+                  set_int(sbalways_h, 1);
+                  emit("do-show-hbar", "");
+                  set_int(sbvis_h, 1);
+               }
+            }
+        }
+        program { name: "hbar_show_notalways";
+           signal: "elm,action,show_notalways,hbar";
+           source: "elm";
+            script {
+               new v;
+               v = get_int(sbalways_h);
+               if (v) {
+                  set_int(sbalways_h, 0);
+                  v = get_int(sbvis_h);
+                  if (!v) {
+                     emit("do-hide-hbar", "");
+                     set_int(sbvis_h, 0);
+                  }
+               }
+            }
+        }
+        program { name: "sb_hbar_show";
+           signal: "do-show-hbar";
+           source: "";
+           action:  STATE_SET "default" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_hbar_clip";
+        }
+        program { name: "sb_hbar_hide";
+           signal: "do-hide-hbar";
+           source: "";
+           action:  STATE_SET "hidden" 0.0;
+           transition: LINEAR 0.5;
+           target: "sb_hbar_clip";
+        }
+
+        program { name: "scroll";
+           signal: "elm,action,scroll";
+           source: "elm";
+           script {
+              new v;
+              v = get_int(sbvis_v);
+               v |= get_int(sbalways_v);
+              if (!v) {
+                  emit("do-show-vbar", "");
+                  set_int(sbvis_v, 1);
+              }
+              v = get_int(sbvis_h);
+               v |= get_int(sbalways_h);
+              if (!v) {
+                  emit("do-show-hbar", "");
+                  set_int(sbvis_h, 1);
+              }
+              v = get_int(sbvis_timer);
+              if (v > 0) cancel_timer(v);
+              v = timer(1.0, "timer0", 0);
+              set_int(sbvis_timer, v);
+           }
+        }
+
+         program { name: "highlight_show";
+            signal: "elm,action,focus_highlight,show";
+            source: "elm";
+            action: STATE_SET "enabled" 0.0;
+            transition: ACCELERATE 0.3;
+            target: "focus_highlight";
+            target: "conf_over";
+         }
+         program { name: "highlight_hide";
+            signal: "elm,action,focus_highlight,hide";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.3;
+            target: "focus_highlight";
+            target: "conf_over";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+#define TEXT_SLIDE_DURATION     10
+
+   group { name: "elm/label/base/default";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+      styles {
+         style { name: "textblock_style";
+            base: "font=Sans font_size=10 color=#000 wrap=word text_class=label";
+            tag:  "br" "\n";
+            tag:  "ps" "ps";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "tab" "\t";
+          }
+       }
+      parts {
+        part { name: "label.swallow.background";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               visible: 1;
+           }
+         }
+        part { name: "label.text.clip";
+            type: RECT;
+           description { state: "default" 0.0;
+               rel1 { relative: 0 0; to: "label.swallow.background"; }
+               rel2 { relative: 1 1; to: "label.swallow.background"; }
+           }
+        }
+        part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           clip_to: "label.text.clip";
+           description { state: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 1.0 1.0;
+               text {
+                  style: "textblock_style";
+                  min: 1 1;
+               }
+           }
+        }
+      }
+   }
+
+   group { name: "elm/label/base_wrap/default";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+      parts {
+         part { name: "label.swallow.background";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+            }
+         }
+        part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              text {
+                 style: "textblock_style";
+                 min: 0 1;
+              }
+           } 
+        }
+      }
+   } 
+
+   group { name: "elm/label/base_wrap_ellipsis/default";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+      parts {
+        part { name: "label.swallow.background";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+           }
+         }
+        part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           multiline: 1;
+           description { state: "default" 0.0;
+              fixed: 0 1; 
+              text {
+                 style: "textblock_style";
+                 min: 0 1;
+              }
+           }
+        }
+      }
+   }
+
+   group { name: "elm/label/base/marker";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+      styles {
+         style { name: "textblock_style2";
+          base: "font=Sans:style=Bold font_size=10 align=center color=#fff wrap=word text_class=label";
+           tag:  "br" "\n";
+           tag:  "ps" "ps";
+          tag:  "hilight" "+ color=#ffff";
+          tag:  "b" "+ color=#ffff";
+          tag:  "tab" "\t";
+        }
+      }
+      parts {
+         part { name: "label.swallow.background";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+            }
+         }
+        part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              text {
+                 style: "textblock_style2";
+                 min: 1 1;
+              }
+           }
+        }
+      }
+   }
+
+   group { name: "elm/label/base_wrap/marker";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+      parts {
+         part { name: "label.swallow.background";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+            }
+         }
+         part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              text {
+                 style: "textblock_style2";
+                 min: 0 1;
+              }
+           }
+        }
+      }
+   }
+
+   group { name: "elm/label/base/slide_long";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+      
+      script {
+        public g_duration, g_stopslide, g_timer_id, g_anim_id;
+          
+        public message(Msg_Type:type, id, ...) {
+           if ((type == MSG_FLOAT_SET) && (id == 0)) {
+              new Float:duration;
+              duration = getarg(2);
+              set_float(g_duration, duration);
+           }
+        }
+        public slide_to_end_anim(val, Float:pos) {
+           new stopflag;
+           new id;
+           stopflag = get_int(g_stopslide);
+           if (stopflag == 1) return;
+           set_tween_state(PART:"elm.text", pos, "slide_begin", 0.0, "slide_end", 0.0);
+           if (pos >= 1.0) {
+              id = timer(0.5, "slide_to_begin", 1);
+              set_int(g_timer_id, id);
+           }
+        }
+        public slide_to_end() {
+           new stopflag;
+           new id;
+           new Float:duration;
+           stopflag = get_int(g_stopslide);
+           if (stopflag == 1) return;
+           duration = get_float(g_duration);
+           id = anim(duration, "slide_to_end_anim", 1);
+           set_int(g_anim_id, id);
+        }
+        public slide_to_begin() {
+           new stopflag;
+           new id;
+           stopflag = get_int(g_stopslide);
+           if (stopflag == 1) return;
+           set_state(PART:"elm.text", "slide_begin", 0.0);
+           id = timer(0.5, "slide_to_end", 1);
+           set_int(g_timer_id, id);
+        }
+        public start_slide() {
+           set_int(g_stopslide, 0);
+           set_state(PART:"elm.text", "slide_begin", 0.0);
+           slide_to_end();
+        }
+        public stop_slide() {
+           new id;
+           set_int(g_stopslide, 1);
+           id = get_int(g_anim_id);
+           cancel_anim(id);
+           id = get_int(g_timer_id);
+           cancel_timer(id);
+           set_state(PART:"elm.text", "default", 0.0);
+        }
+      }
+       
+      parts {
+        part { name: "label.swallow.background";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               visible: 1;
+           }
+         }
+        part { name: "label.text.clip";
+            type: RECT;
+           description { state: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 { relative: 0 0; to: "label.swallow.background"; }
+               rel2 { relative: 1 1; to: "label.swallow.background"; }
+           }
+        }
+        part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           clip_to: "label.text.clip";
+           description { state: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 1.0 1.0;
+               align: 0.0 0.0;
+               text {
+                  style: "textblock_style";
+                  min: 1 1;
+               }
+           }
+            description { state: "slide_end" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 0.0 1.0;
+               align: 1.0 0.0;
+            }
+            description { state: "slide_begin" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 1.0 0.0;
+               rel2.relative: 1.0 1.0;
+               align: 0.0 0.0;
+            }
+        }
+       }
+       programs {
+          program { name: "start_slide";
+             source: "elm";
+             signal: "elm,state,slide,start";
+             script
+               {
+                  start_slide();
+               }
+          }
+          program { name: "stop_slide";
+             source: "elm";
+             signal: "elm,state,slide,stop";
+             script
+               {
+                  stop_slide();
+               }
+          }
+       }
+   }
+   
+
+   group { name: "elm/label/base/slide_short";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+
+      script {
+         public g_duration, g_stopslide, g_timer_id, g_anim_id;
+         
+         public message(Msg_Type:type, id, ...) {
+            if ((type == MSG_FLOAT_SET) && (id == 0)) {
+               new Float:duration;
+               duration = getarg(2);
+               set_float(g_duration, duration);
+            }
+         }
+         public slide_to_end_anim(val, Float:pos) {
+            new stopflag;
+            new id;
+            stopflag = get_int(g_stopslide);
+            if (stopflag == 1) return;
+            set_tween_state(PART:"elm.text", pos, "slide_begin", 0.0, "slide_end", 0.0);
+            if (pos >= 1.0) {
+               id = timer(0.5, "slide_to_begin", 1);
+               set_int(g_timer_id, id);
+            }
+         }
+         public slide_to_end() {
+            new stopflag;
+            new id;
+            new Float:duration;
+            stopflag = get_int(g_stopslide);
+            if (stopflag == 1) return;
+            duration = get_float(g_duration);
+            id = anim(duration, "slide_to_end_anim", 1);
+            set_int(g_anim_id, id);
+         }
+         public slide_to_begin() {
+            new stopflag;
+            new id;
+            stopflag = get_int(g_stopslide);
+            if (stopflag == 1) return;
+            set_state(PART:"elm.text", "slide_begin", 0.0);
+            id = timer(0.5, "slide_to_end", 1);
+            set_int(g_timer_id, id);
+         }
+         public start_slide() {
+            set_int(g_stopslide, 0);
+            set_state(PART:"elm.text", "slide_begin", 0.0);
+            slide_to_end();
+         }
+         public stop_slide() {
+            new id;
+            set_int(g_stopslide, 1);
+            id = get_int(g_anim_id);
+            cancel_anim(id);
+            id = get_int(g_timer_id);
+            cancel_timer(id);
+            set_state(PART:"elm.text", "default", 0.0);
+         }
+      }
+
+      parts {
+        part { name: "label.swallow.background";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               visible: 1;
+           }
+         }
+        part { name: "label.text.clip";
+            type: RECT;
+           description { state: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 { relative: 0 0; to: "label.swallow.background"; }
+               rel2 { relative: 1 1; to: "label.swallow.background"; }
+           }
+        }
+        part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           clip_to: "label.text.clip";
+           description { state: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 1.0 1.0;
+               align: 0.0 0.0;
+               text {
+                  style: "textblock_style";
+                  min: 1 1;
+               }
+           }
+            description { state: "slide_end" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 1.0 0.0;
+               rel2.relative: 1.0 1.0;
+               align: 1.0 0.0;
+            }
+            description { state: "slide_begin" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 0.0 1.0;
+               align: 0.0 0.0;
+            }
+        }
+      }
+      programs {
+         program { name: "start_slide";
+            source: "elm";
+            signal: "elm,state,slide,start";
+            script
+              {
+                 start_slide();
+              }
+         }
+         program { name: "stop_slide";
+            source: "elm";
+            signal: "elm,state,slide,stop";
+            script
+              {
+                 stop_slide();
+              }
+         }
+      }
+   }
+
+   group { name: "elm/label/base/slide_bounce";
+      data.item: "default_font_size" "10";
+      data.item: "min_font_size" "6";
+      data.item: "max_font_size" "60";
+      
+      script {
+         public g_duration, g_stopslide, g_timer_id, g_anim_id;
+         
+         public message(Msg_Type:type, id, ...) {
+            if ((type == MSG_FLOAT_SET) && (id == 0)) {
+               new Float:duration;
+               duration = getarg(2);
+               set_float(g_duration, duration);
+            }
+         }
+         public slide_to_end_anim(val, Float:pos) {
+            new stopflag;
+            new id;
+            stopflag = get_int(g_stopslide);
+            if (stopflag == 1) return;
+            set_tween_state(PART:"elm.text", pos, "slide_begin", 0.0, "slide_end", 0.0);
+            if (pos >= 1.0) {
+               id = timer(0.5, "slide_to_begin", 1);
+               set_int(g_timer_id, id);
+            }
+         }
+         public slide_to_end() {
+            new stopflag;
+            new id;
+            new Float:duration;
+            stopflag = get_int(g_stopslide);
+            if (stopflag == 1) return;
+            duration = get_float(g_duration);
+            id = anim(duration, "slide_to_end_anim", 1);
+            set_int(g_anim_id, id);
+         }
+         public slide_to_begin_anim(val, Float:pos) {
+            new stopflag;
+            new id;
+            stopflag = get_int(g_stopslide);
+            if (stopflag == 1) return;
+            set_tween_state(PART:"elm.text", pos, "slide_end", 0.0, "slide_begin", 0.0);
+            if (pos >= 1.0) {
+               id = timer(0.5, "slide_to_end", 1);
+               set_int(g_timer_id, id);
+            }
+         }
+         public slide_to_begin() {
+            new stopflag;
+            new id;
+            new Float:duration;
+            stopflag = get_int(g_stopslide);
+            if (stopflag == 1) return;
+            duration = get_float(g_duration);
+            id = anim(duration, "slide_to_begin_anim", 1);
+            set_int(g_anim_id, id);
+         }
+         public start_slide() {
+            set_int(g_stopslide, 0);
+            set_state(PART:"elm.text", "slide_begin", 0.0);
+            slide_to_end();
+         }
+         public stop_slide() {
+            new id;
+            set_int(g_stopslide, 1);
+            id = get_int(g_anim_id);
+            cancel_anim(id);
+            id = get_int(g_timer_id);
+            cancel_timer(id);
+            set_state(PART:"elm.text", "default", 0.0);
+         }
+      }
+
+      parts {
+        part { name: "label.swallow.background";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+               visible: 1;
+           }
+         }
+        part { name: "label.text.clip";
+            type: RECT;
+           description { state: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 { relative: 0 0; to: "label.swallow.background"; }
+               rel2 { relative: 1 1; to: "label.swallow.background"; }
+           }
+        }
+        part { name: "elm.text";
+           type: TEXTBLOCK;
+           mouse_events: 0;
+           scale: 1;
+           clip_to: "label.text.clip";
+           description { state: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 1.0 1.0;
+               align: 0.0 0.0;
+               text {
+                  style: "textblock_style";
+                  min: 1 1;
+               }
+           }
+            description { state: "slide_end" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 1.0 0.0;
+               rel2.relative: 1.0 1.0;
+               align: 1.0 0.0;
+            }
+            description { state: "slide_begin" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 0.0 1.0;
+               align: 0.0 0.0;
+            }
+        }
+      }
+      programs {
+         program { name: "start_slide";
+            source: "elm";
+            signal: "elm,state,slide,start";
+            script
+              {
+                 start_slide();
+              }
+         }
+         program { name: "stop_slide";
+            source: "elm";
+            signal: "elm,state,slide,stop";
+            script
+              {
+                 stop_slide();
+              }
+         }
+      }
+   }
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+   group { name: "elm/button/base/default";
+      images {
+        image: "bt_base1.png" COMP;
+        image: "bt_base2.png" COMP;
+        image: "bt_hilight.png" COMP;
+        image: "bt_shine.png" COMP;
+        image: "bt_glow.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+      }
+      parts {
+        part { name: "button_image";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+          min: 15 15;
+              image {
+                 normal: "bt_base2.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "clicked" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "bt_base1.png";
+               image.middle: SOLID;
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 0;
+              visible: 0;
+              align: 0.0 0.5;
+              rel1.offset: 4 4;
+              rel2.offset: 3 -5;
+              rel2.relative: 0.0 1.0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+               fixed: 1 0;
+              visible: 1;
+              aspect: 1.0 1.0;
+//            aspect_preference: VERTICAL;
+              rel2.offset: 4 -5;
+           }
+           description { state: "icononly" 0.0;
+              inherit: "default" 0.0;
+               fixed: 0 0;
+              visible: 1;
+              align: 0.5 0.5;
+//            aspect: 1.0 1.0;
+              rel2.offset: -5 -5;
+              rel2.relative: 1.0 1.0;
+//            aspect_preference: VERTICAL;
+           }
+        }
+         part {
+           name:          "elm.text";
+           type:          TEXT;
+           effect:        SOFT_SHADOW;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to_x: "elm.swallow.content";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: 0 4;
+              rel2.offset: -5 -5;
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 0;
+                 align:    0.5 0.5;
+                  text_class: "button";
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+        part {   name: "over1";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_hilight.png";
+                 border: 7 7 7 0;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "over2";
+           mouse_events: 1;
+           repeat_events: 1;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+              image {
+                 normal: "bt_shine.png";
+                 border: 7 7 7 7;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              visible: 0;
+           }
+        }
+         part { name: "over3";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               image {
+                  normal: "bt_glow.png";
+                  border: 12 12 12 12;
+               }
+              fill.smooth : 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit:  "default" 0.0;
+               color: 255 255 255 255;
+            }
+         }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program {
+           name:   "button_click";
+           signal: "mouse,down,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,press" "";
+           after: "button_click_anim";
+        }
+        program {
+           name:   "button_click_anim";
+           action: STATE_SET "clicked" 0.0;
+           target: "button_image";
+        }
+        program {
+           name:   "button_unclick";
+           signal: "mouse,up,1";
+           source: "over3";
+           action: SIGNAL_EMIT "elm,action,unpress" "";
+           after: "button_unclick_anim";
+        }
+        program {
+           name:   "button_pressed_anim";
+           signal: "elm,anim,activate";
+           source: "elm";
+           action: STATE_SET "clicked" 0.0;
+           target: "button_image";
+           target: "over3";
+           after: "button_unpressed_anim";
+        }
+        program {
+           name:   "button_unpressed_anim";
+           action: STATE_SET "default" 0.0;
+           transition: DECELERATE 0.5;
+           target: "button_image";
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick_anim";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+        }
+        program {
+           name:   "button_click2";
+           signal: "mouse,down,1";
+           source: "over3";
+           action: STATE_SET "clicked" 0.0;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick2";
+           signal: "mouse,up,1";
+           source: "over3";
+           action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.5;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick3";
+           signal: "mouse,clicked,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,click" "";
+        }
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "icononly"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              set_state(PART:"elm.text", "visible", 0.0);
+           }
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+              set_state(PART:"elm.text", "default", 0.0);
+           }
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+           }
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "disable";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "button_image";
+           target: "over1";
+           target: "over2";
+           target: "disabler";
+            after: "disable_text";
+        }
+         program { name: "disable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.text", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.text", "disabled", 0.0);
+           }
+         }
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+           target: "over1";
+           target: "over2";
+           target: "disabler";
+            after: "enable_text";
+        }
+         program { name: "enable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                set_state(PART:"elm.text", "visible", 0.0);
+              else
+                set_state(PART:"elm.text", "default", 0.0);
+           }
+         }
+      }
+   }
+
+   group { name: "elm/button/base/hoversel_vertical/default";
+      alias: "elm/button/base/hoversel_vertical/entry";
+      alias: "elm/button/base/hoversel_horizontal/default";
+      alias: "elm/button/base/hoversel_horizontal/entry";
+      images {
+        image: "bt_base1.png" COMP;
+        image: "bt_base2.png" COMP;
+        image: "bt_hilight.png" COMP;
+        image: "bt_shine.png" COMP;
+        image: "bt_glow.png" COMP;
+        image: "updown.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+      }
+      parts {
+        part { name: "button_image";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              image {
+                 normal: "bt_base2.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "clicked" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "bt_base1.png";
+               image.middle: SOLID;
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+           }
+        }
+        part { name: "arrow";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              image.normal: "updown.png";
+               aspect: 0.6666666666 0.6666666666;
+               aspect_preference: VERTICAL;
+               rel1.offset: 6 7;
+               rel2.offset: 6 -7;
+               rel2.relative: 0.0 1.0;
+               align: 0.0 0.5;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 0;
+              visible: 0;
+              align: 0.0 0.5;
+              rel1 {
+                  to_x: "arrow";
+                  offset: 2 4;
+                  relative: 1.0 0.0;
+               }
+              rel2 {
+                  to_x: "arrow";
+                  offset: 1 -5;
+                  relative: 1.0 1.0;
+               }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+               fixed: 0 0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+              rel2.offset: 2 -5;
+           }
+           description { state: "icononly" 0.0;
+              inherit: "default" 0.0;
+               fixed: 0 0;
+              visible: 1;
+              align: 0.5 0.5;
+              aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "button_image";
+                  offset: -5 -5;
+                  relative: 1.0 1.0;
+               }
+              aspect_preference: VERTICAL;
+           }
+        }
+         part {
+           name:          "elm.text";
+           type:          TEXT;
+           effect:        SOFT_SHADOW;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to_x: "elm.swallow.content";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: 0 4;
+              rel2.offset: -5 -5;
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 0;
+                 align:    0.5 0.5;
+                  text_class: "button";
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+        part {   name: "over1";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_hilight.png";
+                 border: 7 7 7 0;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "over2";
+           mouse_events: 1;
+           repeat_events: 1;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+              image {
+                 normal: "bt_shine.png";
+                 border: 7 7 7 7;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              visible: 0;
+           }
+        }
+         part { name: "over3";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               image {
+                  normal: "bt_glow.png";
+                  border: 12 12 12 12;
+               }
+              fill.smooth : 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit:  "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program {
+           name:   "button_click";
+           signal: "mouse,down,1";
+           source: "over2";
+           action: STATE_SET "clicked" 0.0;
+           target: "button_image";
+        }
+        program {
+           name:   "button_unclick";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+        }
+        program {
+           name:   "button_click2";
+           signal: "mouse,down,1";
+           source: "over3";
+           action: STATE_SET "clicked" 0.0;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick2";
+           signal: "mouse,up,1";
+           source: "over3";
+           action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.5;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick3";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,click" "";
+        }
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "icononly"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              set_state(PART:"elm.text", "visible", 0.0);
+           }
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+              set_state(PART:"elm.text", "default", 0.0);
+           }
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+           }
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "disable";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "button_image";
+           target: "over1";
+           target: "over2";
+           target: "disabler";
+            after: "disable_text";
+        }
+         program { name: "disable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.text", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.text", "disabled", 0.0);
+           }
+         }
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+           target: "over1";
+           target: "over2";
+           target: "disabler";
+            after: "enable_text";
+        }
+         program { name: "enable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                set_state(PART:"elm.text", "visible", 0.0);
+              else
+                set_state(PART:"elm.text", "default", 0.0);
+           }
+         }
+      }
+   }
+
+   group { name: "elm/button/base/hoversel_vertical_entry/default";
+      alias: "elm/button/base/hoversel_vertical_entry/entry";
+      alias: "elm/button/base/hoversel_horizontal_entry/default";
+      alias: "elm/button/base/hoversel_horizontal_entry/entry";
+      images {
+         image: "hoversel_entry_bg.png" COMP;
+      }
+      parts {
+        part { name: "button_image";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+               color: 255 255 255 0;
+               image.normal: "hoversel_entry_bg.png";
+               image.border: 0 0 2 2;
+               fill.smooth: 0;
+           }
+           description { state: "clicked" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              visible: 0;
+              align: 0.0 0.5;
+              rel1.offset: 4 4;
+              rel2.offset: 3 -5;
+              rel2.relative: 0.0 1.0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+              rel2.offset: 4 -5;
+           }
+           description { state: "icononly" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              align: 0.5 0.5;
+              aspect: 1.0 1.0;
+              rel2.offset: -5 -5;
+              rel2.relative: 1.0 1.0;
+              aspect_preference: VERTICAL;
+           }
+        }
+        part { name: "textvis";
+            type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+               visible: 0;
+           }
+           description { state: "visible" 0.0;
+               visible: 1;
+           }
+        }
+         part {
+           name:          "elm.text";
+           type:          TEXT;
+           effect:        SOFT_SHADOW;
+           mouse_events:  0;
+           scale: 1;
+            clip_to:       "textvis";
+           description { state: "default" 0.0;
+              rel1.to_x: "elm.swallow.content";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: 0 4;
+              rel2.offset: -5 -5;
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 0;
+                 align:    0.5 0.5;
+                  text_class: "button";
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              text.min: 1 1;
+           }
+           description { state: "clicked" 0.0;
+              inherit: "default" 0.0;
+              text.min: 1 1;
+              color: 0 0 0 255;
+              color3: 0 0 0 0;
+           }
+        }
+        part { name: "over2";
+            type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+               color: 0 0 0 0;
+           }
+        }
+      }
+      programs {
+        program {
+           name:   "button_click";
+           signal: "mouse,down,1";
+           source: "over2";
+           action: STATE_SET "clicked" 0.0;
+           target: "button_image";
+           target: "elm.text";
+        }
+        program {
+           name:   "button_unclick";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+           target: "elm.text";
+        }
+        program {
+           name:   "button_unclick3";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,click" "";
+        }
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "icononly"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              set_state(PART:"textvis", "visible", 0.0);
+              set_state(PART:"elm.text", "visible", 0.0);
+           }
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+              set_state(PART:"textvis", "default", 0.0);
+              set_state(PART:"elm.text", "default", 0.0);
+           }
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"textvis", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+           }
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.content";
+        }
+      }
+   }
+
+   group { name: "elm/button/base/anchor";
+      images {
+        image: "bt_base1.png" COMP;
+        image: "bt_base2.png" COMP;
+        image: "bt_hilight.png" COMP;
+        image: "bt_shine.png" COMP;
+        image: "bt_glow.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+      }
+      parts {
+        part { name: "button_image";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+          min: 15 15;
+           color: 255 255 255 0;
+              image {
+                 normal: "bt_base2.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+       description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+          color: 255 255 255 255;
+           }
+           description { state: "clicked" 0.0;
+              inherit: "default" 0.0;
+          inherit: "visible" 0.0;
+              image.normal: "bt_base1.png";
+               image.middle: SOLID;
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+          inherit: "visible" 0.0;
+              image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 0;
+              visible: 0;
+              align: 0.0 0.5;
+              rel1.offset: 4 4;
+              rel2.offset: 3 -5;
+              rel2.relative: 0.0 1.0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+               fixed: 1 0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+              rel2.offset: 4 -5;
+           }
+           description { state: "icononly" 0.0;
+              inherit: "default" 0.0;
+               fixed: 0 0;
+              visible: 1;
+              align: 0.5 0.5;
+              aspect: 1.0 1.0;
+              rel2.offset: -5 -5;
+              rel2.relative: 1.0 1.0;
+              aspect_preference: VERTICAL;
+           }
+        }
+         part {
+           name:          "elm.text";
+           type:          TEXT;
+           effect:        SOFT_SHADOW;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to_x: "elm.swallow.content";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: 0 4;
+              rel2.offset: -5 -5;
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 0;
+                 align:    0.5 0.5;
+                  text_class: "button";
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+        part {   name: "over1";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+           color: 255 255 255 0;
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_hilight.png";
+                 border: 7 7 7 0;
+              }
+           }
+       description { state: "visible" 0.0;
+              inherit:  "default" 0.0;
+          color: 255 255 255 255;
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+          inherit:  "visible" 0.0;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "over2";
+           mouse_events: 1;
+           repeat_events: 1;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+              image {
+                 normal: "bt_shine.png";
+                 border: 7 7 7 7;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              visible: 0;
+           }
+        }
+         part { name: "over3";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               image {
+                  normal: "bt_glow.png";
+                  border: 12 12 12 12;
+               }
+              fill.smooth : 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit:  "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+    program {
+           name:   "button_mouse_in";
+           signal: "mouse,in";
+           source: "over2";
+           action: STATE_SET "visible" 0.0;
+           target: "button_image";
+       target: "over1";
+       transition: DECELERATE 0.5;
+        }
+        program {
+           name:   "button_mouse_out";
+           signal: "mouse,out";
+           source: "over2";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+       target: "over1";
+       transition: DECELERATE 0.5;
+        }
+        program {
+           name:   "button_unclick";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: STATE_SET "visible" 0.0;
+           target: "button_image";
+        }
+        program {
+           name:   "button_click2";
+           signal: "mouse,down,1";
+           source: "over3";
+           action: STATE_SET "clicked" 0.0;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick2";
+           signal: "mouse,up,1";
+           source: "over3";
+           action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.5;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick3";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,click" "";
+        }
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "icononly"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              set_state(PART:"elm.text", "visible", 0.0);
+           }
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+              set_state(PART:"elm.text", "default", 0.0);
+           }
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "icononly", 0.0);
+           }
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "disable";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "button_image";
+           target: "over1";
+           target: "over2";
+           target: "disabler";
+            after: "disable_text";
+        }
+         program { name: "disable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.text", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.text", "disabled", 0.0);
+           }
+         }
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+           target: "over1";
+           target: "over2";
+           target: "disabler";
+            after: "enable_text";
+        }
+         program { name: "enable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                set_state(PART:"elm.text", "visible", 0.0);
+              else
+                set_state(PART:"elm.text", "default", 0.0);
+           }
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/toggle/base/default";
+      images {
+         image: "shelf_inset.png" COMP;
+        image: "bt_basew.png" COMP;
+        image: "bt_bases.png" COMP;
+        image: "bt_hilightw.png" COMP;
+        image: "tog_base.png" COMP;
+        image: "tog_dis_base.png" COMP;
+      }
+      parts {
+         part { name: "bg";
+           type: RECT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.relative: 1.0 0.0;
+              rel1.offset: -4 3;
+              rel2.offset: -4 -4;
+              align: 1.0 0.5;
+              min: 96 16;
+              max: 96 16;
+              aspect: 4.0 4.0;
+              aspect_preference: VERTICAL;
+              color: 255 255 255 255;
+           }
+        }
+         part { name: "clipper";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "bg";
+              rel2.to: "bg";
+              color: 255 255 255 255;
+           }
+        }
+         part { name: "button";
+           type: RECT;
+           scale: 1;
+           clip_to: "clipper";
+           mouse_events: 1;
+           dragable {
+              x: 1 1 0;
+              y: 0 0 0;
+              confine: "bg";
+           }
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              rel1.to: "bg";
+              rel2.to: "bg";
+              min: 16 16;
+              max: 16 16;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+              color: 0 0 0 0;
+           }
+        }
+         part { name: "button_events";
+           type: RECT;
+           dragable {
+              events: "button";
+           }
+           description { state: "default" 0.0;
+              rel1.to_x: "bg";
+              rel1.offset: 0 0;
+              rel1.relative: 0.0 0.0;
+              rel2.to_x: "bg";
+              rel2.offset: -1 -1;
+              rel2.relative: 1.0 1.0;
+              color: 0 0 0 0;
+           }
+        }
+         part { name: "onrect";
+           type: RECT;
+           scale: 1;
+           clip_to: "clipper";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "button";
+              rel1.relative: -5.0 0.0;
+              rel2.to: "button";
+              rel2.relative: 0.0 1.0;
+              color: 0 0 0 0;
+           }
+        }
+         part { name: "offrect";
+           type: RECT;
+           scale: 1;
+           clip_to: "clipper";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "button";
+              rel1.relative: 1.0 0.0;
+              rel2.to: "button";
+              rel2.relative: 6.0 1.0;
+              color: 0 0 0 0;
+           }
+        }
+        part { name: "togbase";
+           mouse_events:  0;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+              rel1.to: "onrect";
+              rel2.to: "offrect";
+              image.normal: "tog_base.png";
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "tog_dis_base.png";
+           }
+        }
+         part { name: "elm.offtext";
+           type: TEXT;
+           mouse_events:  0;
+           scale: 1;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+               fixed: 1 1;
+              rel1.to_x: "offrect";
+              rel2.to_x: "offrect";
+              color: 0 0 0 255;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 1;
+                 align:    0.5 0.5;
+                 text:     "OFF";
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+           }
+        }
+         part { name: "elm.ontext";
+           type: TEXT;
+           effect: SOFT_SHADOW;
+           mouse_events:  0;
+           scale: 1;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+               fixed: 1 1;
+              rel1.to_x: "onrect";
+              rel1.offset: 1 1;
+              rel2.to_x: "onrect";
+              rel2.offset: 0 0;
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 1;
+                 align:    0.5 0.5;
+                 text:     "ON";
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+              color3: 0 0 0 24;
+           }
+        }
+        part { name: "conf_over";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              rel1.offset: -1 -1;
+              rel1.to: "bg";
+              rel2.offset: 0 0;
+              rel2.to: "bg";
+              image {
+                 normal: "shelf_inset.png";
+                 border: 7 7 7 7;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+        }
+        part { name: "button0";
+           mouse_events:  0;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+              rel1.to: "button2";
+              rel1.offset: -4 -4;
+              rel2.to: "button2";
+              rel2.offset: 3 3;
+              image {
+                 normal: "bt_bases.png";
+                 border: 11 11 11 11;
+              }
+               image.middle: SOLID;
+              color: 255 255 255 128;
+           }
+        }
+        part { name: "button2";
+           mouse_events:  0;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+              rel1.to: "button";
+              rel1.offset: -2 -2;
+              rel2.to: "button";
+              rel2.offset: 1 1;
+              image {
+                 normal: "bt_basew.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+        }
+        part { name: "button3";
+           mouse_events:  0;
+           clip_to: "clipper";
+           description { state: "default" 0.0;
+              rel1.to: "button2";
+              rel2.to: "button2";
+               rel2.relative: 1.0 0.5;
+              image {
+                  normal: "bt_hilightw.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 0;
+              visible: 0;
+              align: 0.0 0.5;
+              rel1.offset: 4 4;
+              rel2.relative: 0.0 1.0;
+              rel2.offset: 3 -5;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              rel2.offset: 4 -5;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+              visible: 1;
+              aspect: 1.0 1.0;
+           }
+        }
+         part { name: "elm.text";
+           type: TEXT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to_x: "elm.swallow.content";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: 0 4;
+              rel2.to_x: "bg";
+              rel2.relative: 0.0 1.0;
+              rel2.offset: -5 -5;
+              color: 0 0 0 255;
+              text {
+                 font: "Sans,Edje-Vera";
+                 size: 10;
+                 min: 0 0;
+                 align: 0.0 0.5;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program { name:   "drag_end";
+           signal: "mouse,up,1";
+           source: "button";
+           script {
+              new Float:dx, Float:dy;
+              get_drag(PART:"button", dx, dy);
+              if (dx > 0.5)
+                {
+                   set_drag(PART:"button", 1.0, 0.0);
+                   emit("elm,action,toggle,on", "");
+                }
+              else
+                {
+                   set_drag(PART:"button", 0.0, 0.0);
+                   emit("elm,action,toggle,off", "");
+                }
+           }
+        }
+        program { name: "toggle_on";
+           signal: "elm,state,toggle,on";
+           source: "elm";
+           script {
+              set_drag(PART:"button", 100.0, 0.0);
+           }
+        }
+        program { name: "toggle_off";
+           signal: "elm,state,toggle,off";
+           source: "elm";
+           script {
+              set_drag(PART:"button", 0.0, 0.0);
+           }
+        }
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.text";
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.text";
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "disable";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "togbase";
+           target: "elm.offtext";
+           target: "elm.ontext";
+           target: "disabler";
+            after: "disable_text";
+        }
+         program { name: "disable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.text", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.text", "disabled", 0.0);
+
+               get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "disabled", 0.0);
+           }
+         }
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "disabler";
+            after: "enable_text";
+        }
+         program { name: "enable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                set_state(PART:"elm.text", "visible", 0.0);
+              else
+                set_state(PART:"elm.text", "default", 0.0);
+
+               get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "default", 0.0);
+           }
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/clock/flipdigit/default";
+      images {
+         image: "flip_base.png" COMP;
+         image: "flip_base_shad.png" COMP;
+         image: "flip_shad.png" COMP;
+         image: "flip_0t.png" COMP;
+         image: "flip_0b.png" COMP;
+         image: "flip_1t.png" COMP;
+         image: "flip_1b.png" COMP;
+         image: "flip_2t.png" COMP;
+         image: "flip_2b.png" COMP;
+         image: "flip_3t.png" COMP;
+         image: "flip_3b.png" COMP;
+         image: "flip_4t.png" COMP;
+         image: "flip_4b.png" COMP;
+         image: "flip_5t.png" COMP;
+         image: "flip_5b.png" COMP;
+         image: "flip_6t.png" COMP;
+         image: "flip_6b.png" COMP;
+         image: "flip_7t.png" COMP;
+         image: "flip_7b.png" COMP;
+         image: "flip_8t.png" COMP;
+         image: "flip_8b.png" COMP;
+         image: "flip_9t.png" COMP;
+         image: "flip_9b.png" COMP;
+        image: "arrow_up.png" COMP;
+        image: "arrow_down.png" COMP;
+      }
+      script {
+        public v0_cur, v0_pre, v0_lock, v0_next;
+
+       public animator2(val, Float:pos) {
+         new st1[11], st2[11], v;
+
+         v = get_int(v0_cur);
+         snprintf(st1, 10, "%ih", v);
+         snprintf(st2, 10, "%i", v);
+         set_tween_state(PART:"bot", pos, st1, 0.0, st2, 0.0);
+         set_tween_state(PART:"sh", pos, "half", 0.0, "full", 0.0);
+         if (pos >= 1.0) {
+            set_state(PART:"sh", "default", 0.0);
+            set_int(v0_lock, 0);
+            v = get_int(v0_next);
+            if (v >= 0) {
+               set_int(v0_next, -1);
+               message(MSG_INT, 1, v);
+            }
+         }
+       }
+       public animator1(val, Float:pos) {
+         new st1[11], st2[11], v;
+
+         v = get_int(v0_pre);
+         snprintf(st1, 10, "%i", v);
+         snprintf(st2, 10, "%ih", v);
+         set_tween_state(PART:"top", pos, st1, 0.0, st2, 0.0);
+         set_tween_state(PART:"sh", pos, "default", 0.0, "half", 0.0);
+         if (pos >= 1.0) anim(0.2, "animator2", val);
+       }
+       public message(Msg_Type:type, id, ...) {
+         if ((type == MSG_INT) && (id == 1)) {
+            new value, v, buf[11];
+
+            value = getarg(2);
+            if (get_int(v0_lock) == 1) {
+               set_int(v0_next, value);
+               return;
+            }
+            v = get_int(v0_cur);
+            set_int(v0_pre, v);
+            set_int(v0_cur, value);
+            set_int(v0_lock, 1);
+            snprintf(buf, 10, "%i", get_int(v0_pre));
+            set_state(PART:"bot0", buf, 0.0);
+            snprintf(buf, 10, "%ih", get_int(v0_cur));
+            set_state(PART:"bot", buf, 0.0);
+            snprintf(buf, 10, "%i", get_int(v0_cur));
+            set_state(PART:"top0", buf, 0.0);
+            snprintf(buf, 10, "%i", get_int(v0_pre));
+            set_state(PART:"top", buf, 0.0);
+            set_state(PART:"sh", "default", 0.0);
+            anim(0.2, "animator1", 1);
+         }
+       }
+      }
+      parts {
+        part { name: "shad";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.offset: -4 -4;
+              rel1.to: "base";
+              rel2.offset: 3 3;
+              rel2.to: "base";
+              image {
+                  normal: "flip_base_shad.png";
+                 border: 8 8 8 8;
+              }
+           }
+        }
+        part { name: "base";
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+              // FIXME 48x96 should be the native pixel design, right now
+              // its 80x160. fix int he artwork later
+              min: 24 48;
+               aspect: 0.5 0.5;
+//            max: 24 48;
+              image.normal: "flip_base.png";
+           }
+        }
+        part { name: "b";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to: "base";
+              rel1.relative: 0.0 0.5;
+              rel2.to: "base";
+              color: 0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "t";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to: "base";
+              rel2.to: "base";
+              rel2.relative: 1.0 0.5;
+              color: 0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "bot0";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "flip_0b.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_0b.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_1b.png";
+           }
+           description { state: "2" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_2b.png";
+           }
+           description { state: "3" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_3b.png";
+           }
+           description { state: "4" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_4b.png";
+           }
+           description { state: "5" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_5b.png";
+           }
+           description { state: "6" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_6b.png";
+           }
+           description { state: "7" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_7b.png";
+           }
+           description { state: "8" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_8b.png";
+           }
+           description { state: "9" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_9b.png";
+           }
+        }
+        part { name: "sh";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_shad.png";
+           }
+           description { state: "half" 0.0;
+              inherit: "default" 0.0;
+              rel2.relative: 1.0 0.5;
+           }
+           description { state: "full" 0.0;
+              inherit: "default" 0.0;
+              rel2.relative: 1.0 1.0;
+           }
+        }
+        part { name: "bot";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "flip_0b.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_0b.png";
+           }
+           description { state: "0h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_0b.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_1b.png";
+           }
+           description { state: "1h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_1b.png";
+           }
+           description { state: "2" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_2b.png";
+           }
+           description { state: "2h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_2b.png";
+           }
+           description { state: "3" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_3b.png";
+           }
+           description { state: "3h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_3b.png";
+           }
+           description { state: "4" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_4b.png";
+           }
+           description { state: "4h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_4b.png";
+           }
+           description { state: "5" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_5b.png";
+           }
+           description { state: "5h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_5b.png";
+           }
+           description { state: "6" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_6b.png";
+           }
+           description { state: "6h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_6b.png";
+           }
+           description { state: "7" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_7b.png";
+           }
+           description { state: "7h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_7b.png";
+           }
+           description { state: "8" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_8b.png";
+           }
+           description { state: "8h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_8b.png";
+           }
+           description { state: "9" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_9b.png";
+           }
+           description { state: "9h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_9b.png";
+           }
+        }
+        part { name: "top0";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "flip_0t.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_0t.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_1t.png";
+           }
+           description { state: "2" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_2t.png";
+           }
+           description { state: "3" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_3t.png";
+           }
+           description { state: "4" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_4t.png";
+           }
+           description { state: "5" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_5t.png";
+           }
+           description { state: "6" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_6t.png";
+           }
+           description { state: "7" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_7t.png";
+           }
+           description { state: "8" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_8t.png";
+           }
+           description { state: "9" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_9t.png";
+           }
+        }
+        part { name: "top";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "flip_0t.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_0t.png";
+           }
+           description { state: "0h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_0t.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_1t.png";
+           }
+           description { state: "1h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_1t.png";
+           }
+           description { state: "2" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_2t.png";
+           }
+           description { state: "2h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_2t.png";
+           }
+           description { state: "3" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_3t.png";
+           }
+           description { state: "3h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_3t.png";
+           }
+           description { state: "4" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_4t.png";
+           }
+           description { state: "4h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_4t.png";
+           }
+           description { state: "5" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_5t.png";
+           }
+           description { state: "5h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_5t.png";
+           }
+           description { state: "6" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_6t.png";
+           }
+           description { state: "6h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_6t.png";
+           }
+           description { state: "7" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_7t.png";
+           }
+           description { state: "7h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_7t.png";
+           }
+           description { state: "8" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_8t.png";
+           }
+           description { state: "8h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_8t.png";
+           }
+           description { state: "9" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_9t.png";
+           }
+           description { state: "9h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_9t.png";
+           }
+        }
+        part { name: "atop";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              min: 15 15;
+              max: 15 15;
+              align: 0.5 0.0;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "arrow_up.png";
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "abot";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              min: 15 15;
+              max: 15 15;
+              align: 0.5 1.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "arrow_down.png";
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program { name: "load";
+           signal: "load";
+           source: "";
+           script {
+              set_int(v0_cur, 0);
+              set_int(v0_pre, 0);
+              set_int(v0_lock, 0);
+              set_int(v0_next, -1);
+           }
+        }
+        program { name: "edit_on";
+            signal: "elm,state,edit,on";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           target: "atop";
+           target: "abot";
+           target: "t";
+           target: "b";
+        }
+        program { name: "edit_off";
+            signal: "elm,state,edit,off";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "atop";
+           target: "abot";
+           target: "t";
+           target: "b";
+        }
+        program { name: "up";
+           signal: "mouse,down,1";
+           source: "t";
+           action: SIGNAL_EMIT "elm,action,up,start" "";
+        }
+        program { name: "up,stop";
+           signal: "mouse,up,1";
+           source: "t";
+           action: SIGNAL_EMIT "elm,action,up,stop" "";
+        }
+        program { name: "down";
+           signal: "mouse,down,1";
+           source: "b";
+           action: SIGNAL_EMIT "elm,action,down,start" "";
+        }
+        program { name: "down,stop";
+           signal: "mouse,up,1";
+           source: "b";
+           action: SIGNAL_EMIT "elm,action,down,stop" "";
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/clock/flipampm/default";
+      images {
+         image: "flip_base.png" COMP;
+         image: "flip_base_shad.png" COMP;
+         image: "flip_shad.png" COMP;
+         image: "flip_amt.png" COMP;
+         image: "flip_amb.png" COMP;
+         image: "flip_pmt.png" COMP;
+         image: "flip_pmb.png" COMP;
+        image: "arrow_up.png" COMP;
+        image: "arrow_down.png" COMP;
+      }
+      script {
+        public v0_cur, v0_pre, v0_lock, v0_next;
+
+       public animator2(val, Float:pos) {
+         new st1[11], st2[11], v;
+
+         v = get_int(v0_cur);
+         snprintf(st1, 10, "%ih", v);
+         snprintf(st2, 10, "%i", v);
+         set_tween_state(PART:"bot", pos, st1, 0.0, st2, 0.0);
+         set_tween_state(PART:"sh", pos, "half", 0.0, "full", 0.0);
+         if (pos >= 1.0) {
+            set_state(PART:"sh", "default", 0.0);
+            set_int(v0_lock, 0);
+            v = get_int(v0_next);
+            if (v >= 0) {
+               set_int(v0_next, -1);
+               message(MSG_INT, 1, v);
+            }
+         }
+       }
+       public animator1(val, Float:pos) {
+         new st1[11], st2[11], v;
+
+         v = get_int(v0_pre);
+         snprintf(st1, 10, "%i", v);
+         snprintf(st2, 10, "%ih", v);
+         set_tween_state(PART:"top", pos, st1, 0.0, st2, 0.0);
+         set_tween_state(PART:"sh", pos, "default", 0.0, "half", 0.0);
+         if (pos >= 1.0) anim(0.2, "animator2", val);
+       }
+       public message(Msg_Type:type, id, ...) {
+         if ((type == MSG_INT) && (id == 1)) {
+            new value, v, buf[11];
+
+            value = getarg(2);
+            if (get_int(v0_lock) == 1) {
+               set_int(v0_next, value);
+               return;
+            }
+            v = get_int(v0_cur);
+            set_int(v0_pre, v);
+            set_int(v0_cur, value);
+            set_int(v0_lock, 1);
+            snprintf(buf, 10, "%i", get_int(v0_pre));
+            set_state(PART:"bot0", buf, 0.0);
+            snprintf(buf, 10, "%ih", get_int(v0_cur));
+            set_state(PART:"bot", buf, 0.0);
+            snprintf(buf, 10, "%i", get_int(v0_cur));
+            set_state(PART:"top0", buf, 0.0);
+            snprintf(buf, 10, "%i", get_int(v0_pre));
+            set_state(PART:"top", buf, 0.0);
+            set_state(PART:"sh", "default", 0.0);
+            anim(0.2, "animator1", 1);
+         }
+       }
+      }
+      parts {
+        part { name: "shad";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.offset: -4 -4;
+              rel1.to: "base";
+              rel2.offset: 3 3;
+              rel2.to: "base";
+              image {
+                  normal: "flip_base_shad.png";
+                 border: 8 8 8 8;
+              }
+           }
+        }
+        part { name: "base";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+              // FIXME 48x96 should be the native pixel design, right now
+              // its 80x160. fix int he artwork later
+               aspect: 0.5 0.5;
+              min: 24 48;
+//            max: 24 48;
+              image.normal: "flip_base.png";
+           }
+        }
+        part { name: "b";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "base";
+              rel1.relative: 0.0 0.5;
+              rel2.to: "base";
+              color: 0 0 0 0;
+           }
+        }
+        part { name: "t";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "base";
+              rel2.to: "base";
+              rel2.relative: 1.0 0.5;
+              color: 0 0 0 0;
+           }
+        }
+        part { name: "bot0";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "flip_amb.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_amb.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_pmb.png";
+           }
+        }
+        part { name: "sh";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_shad.png";
+           }
+           description { state: "half" 0.0;
+              inherit: "default" 0.0;
+              rel2.relative: 1.0 0.5;
+           }
+           description { state: "full" 0.0;
+              inherit: "default" 0.0;
+              rel2.relative: 1.0 1.0;
+           }
+        }
+        part { name: "bot";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "flip_amb.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_amb.png";
+           }
+           description { state: "0h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_amb.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel2.relative: 1.0 1.0;
+              image.normal: "flip_pmb.png";
+           }
+           description { state: "1h" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_pmb.png";
+           }
+        }
+        part { name: "top0";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "flip_amt.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_amt.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "flip_pmt.png";
+           }
+        }
+        part { name: "top";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "flip_amt.png";
+           }
+           description { state: "0" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_amt.png";
+           }
+           description { state: "0h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_amt.png";
+           }
+           description { state: "1" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              rel1.relative: 0.0 0.0;
+              image.normal: "flip_pmt.png";
+           }
+           description { state: "1h" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+              image.normal: "flip_pmt.png";
+           }
+        }
+        part { name: "atop";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              min: 15 15;
+              max: 15 15;
+              align: 0.5 0.0;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "arrow_up.png";
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "abot";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              min: 15 15;
+              max: 15 15;
+              align: 0.5 1.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "arrow_down.png";
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program { name: "load";
+           signal: "load";
+           source: "";
+           script {
+              set_int(v0_cur, 0);
+              set_int(v0_pre, 0);
+              set_int(v0_lock, 0);
+              set_int(v0_next, -1);
+           }
+        }
+        program { name: "edit_on";
+            signal: "elm,state,edit,on";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           target: "atop";
+           target: "abot";
+        }
+/*
+        program { name: "edit_off";
+            signal: "elm,state,edit,off";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "atop";
+           target: "abot";
+        }
+ */
+        program { name: "up";
+           signal: "mouse,down,1";
+           source: "t";
+           action: SIGNAL_EMIT "elm,action,up,start" "";
+        }
+        program { name: "up,stop";
+           signal: "mouse,up,1";
+           source: "t";
+           action: SIGNAL_EMIT "elm,action,up,stop" "";
+        }
+        program { name: "down";
+           signal: "mouse,down,1";
+           source: "b";
+           action: SIGNAL_EMIT "elm,action,down,start" "";
+        }
+        program { name: "down,stop";
+           signal: "mouse,up,1";
+           source: "b";
+           action: SIGNAL_EMIT "elm,action,down,stop" "";
+        }
+      }
+   }
+
+   ///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/menu/item/default";
+       images {
+           image: "bt_base1.png" COMP;
+           image: "bt_base2.png" COMP;
+           image: "bt_hilight.png" COMP;
+           image: "bt_shine.png" COMP;
+           image: "bt_glow.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       script {
+            public menu_text_visible; //0:hide (default), 1:visible
+            public menu_disable; //0:enable, 1:disable
+       }
+       parts {
+           part { name: "item_image";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   image {
+                       normal: "bt_base2.png";
+                       border: 7 7 7 7;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 255;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   inherit: "visible" 0.0;
+                   image.normal: "bt_base1.png";
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+               }
+           }
+           part { name: "item_image_disabled";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   visible: 1;
+                   align: 0.0 0.5;
+                   rel1.offset: 4 4;
+                   rel2.offset: 3 -5;
+                   rel2.relative: 0.0 1.0;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   rel2.offset: 4 -5;
+               }
+           }
+           part {
+               name:          "elm.text";
+               type:          TEXT;
+               mouse_events:  0;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   rel1.to_x: "elm.swallow.content";
+                   rel1.relative: 1.0 0.0;
+                   rel1.offset: 5 7;
+                   rel2.offset: -10 -8;
+                   color: 0 0 0 255;
+                   text {
+                       font:     "Sans,Edje-Vera";
+                       size:     10;
+                       min:      1 1;
+                       align:    0.0 0.5;
+                       text_class: "menu_item";
+                   }
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   inherit: "visible" 0.0;
+                   color: 254 254 254 255;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+               }
+               description { state: "disabled_visible" 0.0;
+                   inherit: "default" 0.0;
+                   inherit: "visible" 0.0;
+                   color: 0 0 0 128;
+               }
+           }
+           part {        name: "over1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+               description { state: "visible" 0.0;
+                   inherit:  "default" 0.0;
+                   color: 255 255 255 255;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+               }
+           }
+           part {        name: "over_disabled";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "over2";
+               mouse_events: 1;
+               repeat_events: 1;
+               ignore_flags: ON_HOLD;
+               description { state: "default" 0.0;
+                   image {
+                       normal: "bt_shine.png";
+                       border: 7 7 7 7;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 0;
+               }
+           }
+           part { name: "over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "disabler";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+           }
+       }
+       programs {
+          //
+           program {
+               name:   "item_mouse_in";
+               signal: "mouse,in";
+               source: "over2";
+               action: SIGNAL_EMIT "elm,action,activate" "";
+               after: "item_mouse_in_2";
+               after: "item_mouse_in_3";
+           }
+           program {
+               name:   "item_mouse_in_2";
+               transition: DECELERATE 0.5;
+               script {
+                   new v, d;
+                   v = get_int(menu_text_visible);
+                   d = get_int(menu_disable);
+
+                   if (v==1 && d==0)
+                        run_program(PROGRAM:"selected_text");
+               }
+           }
+           program {
+               name:   "item_mouse_in_3";
+               action : STATE_SET "visible" 0.0;
+               target: "item_image";
+               target: "over1";
+               transition: DECELERATE 0.5;
+           }
+           program {
+               name:   "selected_text";
+               action: STATE_SET "selected" 0.0;
+               target: "elm.text";
+               transition: DECELERATE 0.5;
+           }
+           //
+
+           //
+           program {
+               name:   "item_mouse_out";
+               signal: "mouse,out";
+               source: "over2";
+               after: "item_mouse_out_2";
+               after: "item_mouse_out_3";
+           }
+           program {
+               name:   "item_mouse_out_2";
+               transition: DECELERATE 0.5;
+               script {
+                   new v, d;
+                   v = get_int(menu_text_visible);
+                   d = get_int(menu_disable);
+
+                   if (v==1 && d==0)
+                        run_program(PROGRAM:"visible_text");
+               }
+           }
+           program {
+               name:   "item_mouse_out_3";
+               action: STATE_SET "default" 0.0;
+               target: "item_image";
+               target: "over1";
+               transition: DECELERATE 0.5;
+           }
+           program {
+               name:   "visible_text";
+               action: STATE_SET "visible" 0.0;
+               target: "elm.text";
+               transition: DECELERATE 0.5;
+           }
+           //
+
+           program {
+               name:   "item_unclick";
+               signal: "mouse,up,1";
+               source: "over2";
+               action: STATE_SET "visible" 0.0;
+               target: "item_image";
+           }
+           program {
+               name:   "item_click2";
+               signal: "mouse,down,1";
+               source: "over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "over3";
+           }
+           program {
+               name:   "item_unclick2";
+               signal: "mouse,up,1";
+               source: "over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "over3";
+           }
+           program {
+               name:   "item_unclick3";
+               signal: "mouse,up,1";
+               source: "over2";
+               action: SIGNAL_EMIT "elm,action,click" "";
+           }
+           program { name: "text_show";
+               signal: "elm,state,text,visible";
+               source: "elm";
+               script {
+                   set_int(menu_text_visible, 1);
+                   set_state(PART:"elm.text", "visible", 0.0);
+               }
+           }
+           program { name: "text_hide";
+               signal: "elm,state,text,hidden";
+               source: "elm";
+               script {
+                   set_int(menu_text_visible, 0);
+                   set_state(PART:"elm.text", "default", 0.0);
+               }
+           }
+           program { name: "disable";
+               signal: "elm,state,disabled";
+               source: "elm";
+               action: STATE_SET "disabled" 0.0;
+               target: "item_image";
+               target: "item_image_disabled";
+               target: "over1";
+               target: "over2";
+               target: "over_disabled";
+               target: "disabler";
+               after: "disable_text";
+           }
+           program { name: "disable_text";
+               script {
+                   new v;
+                   v = get_int(menu_text_visible);
+                   if (v==1)
+                    set_state(PART:"elm.text", "disabled_visible", 0.0);
+                   else if (v==0)
+                    set_state(PART:"elm.text", "disabled", 0.0);
+                   set_int(menu_disable, 1);
+               }
+           }
+           program { name: "enable";
+               signal: "elm,state,enabled";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "item_image";
+               target: "item_image_disabled";
+               target: "over1";
+               target: "over2";
+               target: "over_disabled";
+               target: "disabler";
+               after: "enable_text";
+           }
+           program { name: "enable_text";
+               script {
+                   new v;
+                   v = get_int(menu_text_visible);
+                   if (v==1)
+                    set_state(PART:"elm.text", "visible", 0.0);
+                   else  if (v==0)
+                    set_state(PART:"elm.text", "default", 0.0);
+                   set_int(menu_disable, 0);
+               }
+           }
+       }
+   }
+
+   group { name: "elm/menu/item_with_submenu/default";
+       images {
+           image: "bt_base1.png" COMP;
+           image: "bt_base2.png" COMP;
+           image: "bt_hilight.png" COMP;
+           image: "bt_shine.png" COMP;
+           image: "bt_glow.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+           image: "arrow_right.png" COMP;
+       }
+       script {
+            public menu_text_visible; //0:hide (default), 1:visible
+            public menu_disable; //0:enable, 1:disable
+       }
+       parts {
+           part { name: "item_image";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   image {
+                       normal: "bt_base2.png";
+                       border: 7 7 7 7;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 255;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   inherit: "visible" 0.0;
+                   image.normal: "bt_base1.png";
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+               }
+           }
+           part { name: "item_image_disabled";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "arrow";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 255;
+                   align: 1.0 0.5;
+                   aspect: 1 1;
+                   aspect_preference: BOTH;
+                   image {
+                       normal: "arrow_right.png";
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   visible: 1;
+                   align: 0.0 0.5;
+                   rel1.offset: 4 4;
+                   rel2.offset: 3 -5;
+                   rel2.relative: 0.0 1.0;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   rel2.offset: 4 -5;
+               }
+           }
+           part {
+               name:          "elm.text";
+               type:          TEXT;
+               mouse_events:  0;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   rel1.to_x: "elm.swallow.content";
+                   rel1.relative: 1.0 0.0;
+                   rel1.offset: 5 7;
+                   rel2.offset: -10 -8;
+                   color: 0 0 0 255;
+                   text {
+                       font:     "Sans,Edje-Vera";
+                       size:     10;
+                       min:      1 1;
+                       align:    0.0 0.5;
+                       text_class: "menu_item";
+                   }
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   inherit: "visible" 0.0;
+                   color: 254 254 254 255;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+               }
+               description { state: "disabled_visible" 0.0;
+                   inherit: "default" 0.0;
+                   inherit: "visible" 0.0;
+                   color: 0 0 0 128;
+               }
+           }
+           part {        name: "over1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+               description { state: "visible" 0.0;
+                   inherit:  "default" 0.0;
+                   color: 255 255 255 255;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+               }
+           }
+           part { name: "over_disabled";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "over2";
+               mouse_events: 1;
+               repeat_events: 1;
+               ignore_flags: ON_HOLD;
+               description { state: "default" 0.0;
+                   image {
+                       normal: "bt_shine.png";
+                       border: 7 7 7 7;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 0;
+               }
+           }
+           part { name: "over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "disabler";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+           }
+       }
+       programs {
+           //
+           program {
+               name:   "item_mouse_in";
+               signal: "mouse,in";
+               source: "over2";
+               action: SIGNAL_EMIT "elm,action,activate" "";
+               after: "item_mouse_in_2";
+               after: "item_mouse_in_3";
+           }
+           program {
+               name:   "item_mouse_in_2";
+               transition: DECELERATE 0.5;
+               script {
+                   new v, d;
+                   v = get_int(menu_text_visible);
+                   d = get_int(menu_disable);
+
+                   if (v==1 && d==0)
+                        run_program(PROGRAM:"selected_text");
+               }
+           }
+           program {
+               name:   "item_mouse_in_3";
+               action : STATE_SET "visible" 0.0;
+               target: "item_image";
+               target: "over1";
+               transition: DECELERATE 0.5;
+           }
+           program {
+               name:   "selected_text";
+               action: STATE_SET "selected" 0.0;
+               target: "elm.text";
+               transition: DECELERATE 0.5;
+           }
+           //
+
+           //
+           program {
+               name:   "item_mouse_out";
+               signal: "mouse,out";
+               source: "over2";
+               after: "item_mouse_out_2";
+               after: "item_mouse_out_3";
+           }
+           program {
+               name:   "item_mouse_out_2";
+               transition: DECELERATE 0.5;
+               script {
+                   new v, d;
+                   v = get_int(menu_text_visible);
+                   d = get_int(menu_disable);
+
+                   if (v==1 && d==0)
+                        run_program(PROGRAM:"visible_text");
+               }
+           }
+           program {
+               name:   "item_mouse_out_3";
+               action: STATE_SET "default" 0.0;
+               target: "item_image";
+               target: "over1";
+               transition: DECELERATE 0.5;
+           }
+           program {
+               name:   "visible_text";
+               action: STATE_SET "visible" 0.0;
+               target: "elm.text";
+               transition: DECELERATE 0.5;
+           }
+           //
+
+           program {
+               name:   "item_unclick";
+               signal: "mouse,up,1";
+               source: "over2";
+               action: STATE_SET "visible" 0.0;
+               target: "item_image";
+           }
+           program {
+               name:   "item_click2";
+               signal: "mouse,down,1";
+               source: "over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "over3";
+           }
+           program {
+               name:   "item_unclick2";
+               signal: "mouse,up,1";
+               source: "over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "over3";
+           }
+           program {
+               name:   "item_unclick3";
+               signal: "mouse,up,1";
+               source: "over2";
+               action: SIGNAL_EMIT "elm,action,click" "";
+           }
+           program {
+               name:   "menu_open";
+               signal: "mouse,in";
+               source: "over2";
+               action: SIGNAL_EMIT "elm,action,open" "";
+           }
+            program { name: "text_show";
+               signal: "elm,state,text,visible";
+               source: "elm";
+               script {
+                   set_int(menu_text_visible, 1);
+                   set_state(PART:"elm.text", "visible", 0.0);
+               }
+           }
+           program { name: "text_hide";
+               signal: "elm,state,text,hidden";
+               source: "elm";
+               script {
+                   set_int(menu_text_visible, 0);
+                   set_state(PART:"elm.text", "default", 0.0);
+               }
+           }
+           program { name: "disable";
+               signal: "elm,state,disabled";
+               source: "elm";
+               action: STATE_SET "disabled" 0.0;
+               target: "item_image";
+               target: "item_image_disabled";
+               target: "over1";
+               target: "over2";
+               target: "over_disabled";
+               target: "disabler";
+               after: "disable_text";
+           }
+           program { name: "disable_text";
+               script {
+                   new st[31];
+                   new Float:vl;
+                   get_state(PART:"elm.text", st, 30, vl);
+                   if (!strcmp(st, "visible"))
+                   set_state(PART:"elm.text", "disabled_visible", 0.0);
+                   else if (!strcmp(st, "default"))
+                   set_state(PART:"elm.text", "disabled", 0.0);
+               }
+           }
+           program { name: "enable";
+               signal: "elm,state,enabled";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "item_image";
+               target: "item_image_disabled";
+               target: "over1";
+               target: "over2";
+               target: "over_disabled";
+               target: "disabler";
+               after: "enable_text";
+           }
+           program { name: "enable_text";
+               script {
+                   new v;
+                   v = get_int(menu_text_visible);
+                   if (v==1)
+                    set_state(PART:"elm.text", "visible", 0.0);
+                   else  if (v==0)
+                    set_state(PART:"elm.text", "default", 0.0);
+                   set_int(menu_disable, 0);
+               }
+           }
+       }
+   }
+
+   group { name: "elm/menu/separator/default";
+       images {
+           image: "separator_h.png" COMP;
+       }
+       parts {
+           part { name: "separator"; // separator group
+               description { state: "default" 0.0;
+                   min: 2 2;
+                   rel1.offset: 4 4;
+                   rel2.offset: -5 -5;
+                   image {
+                       normal: "separator_h.png";
+                   }
+                   fill {
+                       smooth: 0;
+                   }
+               }
+           }
+       }
+   }
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/clock/base-all/default";
+      parts {
+        part { name: "d0";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.0000000 0.0;
+              rel2.relative: 0.1250000 1.0;
+           }
+        }
+        part { name: "d1";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.1250000 0.0;
+              rel2.relative: 0.2500000 1.0;
+           }
+        }
+        part { name: "c0";
+           type: SWALLOW;
+           type: TEXT;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.relative: 0.2500000 0.0;
+              rel2.relative: 0.3125000 1.0;
+              color: 0 0 0 255;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 text:     ":";
+                 size:     10;
+                 min:      1 1;
+                 align:    0.5 0.5;
+              }
+           }
+        }
+        part { name: "d2";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.3125000 0.0;
+              rel2.relative: 0.4375000 1.0;
+           }
+        }
+        part { name: "d3";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.4375000 0.0;
+              rel2.relative: 0.5625000 1.0;
+           }
+        }
+        // (if seconds)
+        part { name: "c1";
+           type: SWALLOW;
+           type: TEXT;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.relative: 0.5625000 0.0;
+              rel2.relative: 0.6250000 1.0;
+              color: 0 0 0 255;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 text:     ":";
+                 size:     10;
+                 min:      1 1;
+                 align:    0.5 0.5;
+              }
+           }
+        }
+        // (if seconds)
+        part { name: "d4";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.6250000 0.0;
+              rel2.relative: 0.7500000 1.0;
+           }
+        }
+        // (if seconds)
+        part { name: "d5";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.7500000 0.0;
+              rel2.relative: 0.8750000 1.0;
+           }
+        }
+        // (if am_pm)
+        part { name: "ampm";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.8750000 0.0;
+              rel2.relative: 1.0 1.0;
+           }
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/clock/base-seconds/default";
+      parts {
+        part { name: "d0";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.000000000 0.0;
+              rel2.relative: 0.142857143 1.0;
+           }
+        }
+        part { name: "d1";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.142857143 0.0;
+              rel2.relative: 0.285714286 1.0;
+           }
+        }
+        part { name: "c0";
+           type: SWALLOW;
+           type: TEXT;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.relative: 0.285714286 0.0;
+              rel2.relative: 0.357142857 1.0;
+              color: 0 0 0 255;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 text:     ":";
+                 size:     10;
+                 min:      1 1;
+                 align:    0.5 0.5;
+              }
+           }
+        }
+        part { name: "d2";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.357142857 0.0;
+              rel2.relative: 0.500000000 1.0;
+           }
+        }
+        part { name: "d3";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.500000000 0.0;
+              rel2.relative: 0.642857143 1.0;
+           }
+        }
+        // (if seconds)
+        part { name: "c1";
+           type: SWALLOW;
+           type: TEXT;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.relative: 0.642857143 0.0;
+              rel2.relative: 0.714285714 1.0;
+              color: 0 0 0 255;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 text:     ":";
+                 size:     10;
+                 min:      1 1;
+                 align:    0.5 0.5;
+              }
+           }
+        }
+        // (if seconds)
+        part { name: "d4";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.714285714 0.0;
+              rel2.relative: 0.857142857 1.0;
+           }
+        }
+        // (if seconds)
+        part { name: "d5";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.857142857 0.0;
+              rel2.relative: 1.000000000 1.0;
+           }
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/clock/base-am_pm/default";
+      parts {
+        part { name: "d0";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.000000000 0.0;
+              rel2.relative: 0.181818182 1.0;
+           }
+        }
+        part { name: "d1";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.181818182 0.0;
+              rel2.relative: 0.363636364 1.0;
+           }
+        }
+        part { name: "c0";
+           type: SWALLOW;
+           type: TEXT;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.relative: 0.363636364 0.0;
+              rel2.relative: 0.454545455 1.0;
+              color: 0 0 0 255;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 text:     ":";
+                 size:     10;
+                 min:      1 1;
+                 align:    0.5 0.5;
+              }
+           }
+        }
+        part { name: "d2";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.454545455 0.0;
+              rel2.relative: 0.636363636 1.0;
+           }
+        }
+        part { name: "d3";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.636363636 0.0;
+              rel2.relative: 0.818181818 1.0;
+           }
+        }
+        // (if am_pm)
+        part { name: "ampm";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.818181818 0.0;
+              rel2.relative: 1.0 1.0;
+           }
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/clock/base/default";
+      parts {
+        part { name: "d0";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.000000000 0.0;
+              rel2.relative: 0.222222222 1.0;
+           }
+        }
+        part { name: "d1";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.222222222 0.0;
+              rel2.relative: 0.444444444 1.0;
+           }
+        }
+        part { name: "c0";
+           type: SWALLOW;
+           type: TEXT;
+           mouse_events:  0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.relative: 0.444444444 0.0;
+              rel2.relative: 0.555555556 1.0;
+              color: 0 0 0 255;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 text:     ":";
+                 size:     10;
+                 min:      1 1;
+                 align:    0.5 0.5;
+              }
+           }
+        }
+        part { name: "d2";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.555555556 0.0;
+              rel2.relative: 0.777777778 1.0;
+           }
+        }
+        part { name: "d3";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.relative: 0.777777778 0.0;
+              rel2.relative: 1.000000000 1.0;
+           }
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/frame/base/default";
+       images {
+           image: "frame_1.png" COMP;
+           image: "frame_2.png" COMP;
+           image: "dia_grad.png" COMP;
+       }
+       parts {
+           part { name: "base0";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "dia_grad.png";
+                   rel1.to: "over";
+                   rel2.to: "over";
+                   fill {
+                       smooth: 0;
+                       size {
+                           relative: 0.0 1.0;
+                           offset: 64 0;
+                       }
+                   }
+               }
+           }
+           part { name: "base";
+               mouse_events:  0;
+               description { state:    "default" 0.0;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 9 9;
+                   image {
+                       normal: "frame_2.png";
+                       border: 5 5 32 26;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "elm.text";
+               type: TEXT;
+               mouse_events:   0;
+               scale: 1;
+               description { state: "default" 0.0;
+                   align: 0.0 0.0;
+                   fixed: 0 1;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: 6 6;
+                   }
+                   rel2 {
+                       relative: 1.0 0.0;
+                       offset: -7 6;
+                   }
+                   color: 0 0 0 64;
+                   text {
+                       font: "Sans:style=Bold,Edje-Vera-Bold";
+                       size: 10;
+                       min: 1 1;
+                       max: 1 1;
+                       align: 0.0 0.0;
+                   }
+               }
+           }
+           part { name: "over";
+               mouse_events:  0;
+               description { state:    "default" 0.0;
+                   rel1.offset: 4 4;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 5 5;
+                   image {
+                       normal: "frame_1.png";
+                       border: 2 2 28 22;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   align: 0.0 0.0;
+                   rel1 {
+                       to_y: "elm.text";
+                       relative: 0.0 1.0;
+                       offset: 8 2;
+                   }
+                   rel2.offset: -9 -9;
+               }
+           }
+       }
+   }
+
+   group { name: "elm/frame/base/pad_small";
+       parts {
+           part { name: "b0";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 4 4;
+                   max: 4 4;
+                   align: 0.0 0.0;
+               }
+           }
+           part { name: "b1";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 4 4;
+                   max: 4 4;
+                   align: 1.0 1.0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "b0";
+                       relative: 1.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "b1";
+                       relative: 0.0 0.0;
+                       offset: -1 -1;
+                   }
+               }
+           }
+       }
+   }
+
+   group { name: "elm/frame/base/pad_medium";
+       parts {
+           part { name: "b0";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 8 8;
+                   max: 8 8;
+                   align: 0.0 0.0;
+               }
+           }
+           part { name: "b1";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 8 8;
+                   max: 8 8;
+                   align: 1.0 1.0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "b0";
+                       relative: 1.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "b1";
+                       relative: 0.0 0.0;
+                       offset: -1 -1;
+                   }
+               }
+           }
+       }
+   }
+
+   group { name: "elm/frame/base/pad_large";
+       parts {
+           part { name: "b0";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 16 16;
+                   max: 16 16;
+                   align: 0.0 0.0;
+               }
+           }
+           part { name: "b1";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 16 16;
+                   max: 16 16;
+                   align: 1.0 1.0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "b0";
+                       relative: 1.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "b1";
+                       relative: 0.0 0.0;
+                       offset: -1 -1;
+                   }
+               }
+           }
+       }
+   }
+
+   group { name: "elm/frame/base/pad_huge";
+       parts {
+           part { name: "b0";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 32 32;
+                   max: 32 32;
+                   align: 0.0 0.0;
+               }
+           }
+           part { name: "b1";
+               mouse_events:  0;
+               type: RECT;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   min: 32 32;
+                   max: 32 32;
+                   align: 1.0 1.0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "b0";
+                       relative: 1.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "b1";
+                       relative: 0.0 0.0;
+                       offset: -1 -1;
+                   }
+               }
+           }
+       }
+   }
+
+   group { name: "elm/frame/base/outdent_top";
+       images {
+           image: "outdent-top.png" COMP;
+       }
+       parts {
+           part { name: "base0";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "outdent-top.png";
+                   image.border: 0 0 0 13;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.offset: 2 2;
+                   rel2.offset: -3 -13;
+               }
+           }
+       }
+   }
+
+   group { name: "elm/frame/base/outdent_bottom";
+       images {
+           image: "outdent-bottom.png" COMP;
+       }
+       parts {
+           part { name: "base0";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "outdent-bottom.png";
+                   image.border: 0 0 13 0;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.offset: 2 12;
+                   rel2.offset: -3 -3;
+               }
+           }
+       }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/label/base/tooltip";
+      styles {
+         style { name: "tooltip_style";
+            base: "font=Sans font_size=8 color=#666 wrap=word";
+            tag:  "br" "\n";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "tab" "\t";
+         }
+      }
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               text {
+                  style: "tooltip_style";
+                  min: 1 1;
+               }
+            }
+         }
+      }
+   }
+
+   group { name: "elm/tooltip/base/default";
+       min: 30 30;
+       data {
+           item: "pad_x" "20";
+           item: "pad_y" "20";
+           item: "pad_border_x" "10";
+           item: "pad_border_y" "10";
+           item: "hide_timeout" "0.35"; /**< tooltip is hidden after this amount, keep in sync with hide animations */
+       }
+       images {
+           image: "tooltip-base.png" COMP;
+           image: "tooltip-corner-top-left-tip.png" COMP;
+           image: "tooltip-corner-top-right-tip.png" COMP;
+           image: "tooltip-corner-bottom-left-tip.png" COMP;
+           image: "tooltip-corner-bottom-right-tip.png" COMP;
+           image: "tooltip-edge-left-tip.png" COMP;
+           image: "tooltip-edge-right-tip.png" COMP;
+           image: "tooltip-edge-bottom-tip.png" COMP;
+           image: "tooltip-edge-top-tip.png" COMP;
+       }
+       script {
+          hide_corners() {
+             set_state(PART:"corner-top-left", "default", 0.0);
+             set_state(PART:"corner-top-right", "default", 0.0);
+             set_state(PART:"corner-bottom-left", "default", 0.0);
+             set_state(PART:"corner-bottom-right", "default", 0.0);
+          }
+          hide_edges() {
+             set_state(PART:"clipper-edge-left", "default", 0.0);
+             set_state(PART:"clipper-edge-right", "default", 0.0);
+             set_state(PART:"clipper-edge-top", "default", 0.0);
+             set_state(PART:"clipper-edge-bottom", "default", 0.0);
+          }
+
+          show_corner_top_left() {
+             set_state(PART:"corner-top-left", "visible", 0.0);
+
+             set_state(PART:"corner-top-right", "default", 0.0);
+             set_state(PART:"corner-bottom-left", "default", 0.0);
+             set_state(PART:"corner-bottom-right", "default", 0.0);
+             hide_edges();
+          }
+          show_corner_top_right() {
+             set_state(PART:"corner-top-right", "visible", 0.0);
+
+             set_state(PART:"corner-top-left", "default", 0.0);
+             set_state(PART:"corner-bottom-left", "default", 0.0);
+             set_state(PART:"corner-bottom-right", "default", 0.0);
+             hide_edges();
+          }
+
+          show_corner_bottom_left() {
+             set_state(PART:"corner-bottom-left", "visible", 0.0);
+
+             set_state(PART:"corner-bottom-right", "default", 0.0);
+             set_state(PART:"corner-top-left", "default", 0.0);
+             set_state(PART:"corner-top-right", "default", 0.0);
+             hide_edges();
+          }
+          show_corner_bottom_right() {
+             set_state(PART:"corner-bottom-right", "visible", 0.0);
+
+             set_state(PART:"corner-bottom-left", "default", 0.0);
+             set_state(PART:"corner-top-left", "default", 0.0);
+             set_state(PART:"corner-top-right", "default", 0.0);
+             hide_edges();
+          }
+
+          show_edge_left(Float:val) {
+             set_state(PART:"clipper-edge-left", "visible", 0.0);
+             set_drag(PART:"edge-drag-left", 0.0, val);
+
+             set_state(PART:"clipper-edge-right", "default", 0.0);
+             set_state(PART:"clipper-edge-top", "default", 0.0);
+             set_state(PART:"clipper-edge-bottom", "default", 0.0);
+             hide_corners();
+          }
+          show_edge_right(Float:val) {
+             set_state(PART:"clipper-edge-right", "visible", 0.0);
+             set_drag(PART:"edge-drag-right", 0.0, val);
+
+             set_state(PART:"clipper-edge-left", "default", 0.0);
+             set_state(PART:"clipper-edge-top", "default", 0.0);
+             set_state(PART:"clipper-edge-bottom", "default", 0.0);
+             hide_corners();
+          }
+
+          show_edge_top(Float:val) {
+             set_state(PART:"clipper-edge-top", "visible", 0.0);
+             set_drag(PART:"edge-drag-top", val, 0.0);
+
+             set_state(PART:"clipper-edge-bottom", "default", 0.0);
+             set_state(PART:"clipper-edge-left", "default", 0.0);
+             set_state(PART:"clipper-edge-right", "default", 0.0);
+             hide_corners();
+          }
+          show_edge_bottom(Float:val) {
+             set_state(PART:"clipper-edge-bottom", "visible", 0.0);
+             set_drag(PART:"edge-drag-bottom", val, 0.0);
+
+             set_state(PART:"clipper-edge-top", "default", 0.0);
+             set_state(PART:"clipper-edge-left", "default", 0.0);
+             set_state(PART:"clipper-edge-right", "default", 0.0);
+             hide_corners();
+          }
+
+          public message(Msg_Type:type, id, ...) {
+             if ((type == MSG_FLOAT_SET) && (id == 1)) {
+                new Float:x, Float:y;
+
+                x = getfarg(2);
+                y = getfarg(3);
+
+                if (x < 0.0)
+                  {
+                     if (y < 0.0)      show_corner_top_left();
+                     else if (y > 1.0) show_corner_bottom_left();
+                     else              show_edge_left(y);
+                  }
+                else if (x > 1.0)
+                  {
+                     if (y < 0.0)      show_corner_top_right();
+                     else if (y > 1.0) show_corner_bottom_right();
+                     else              show_edge_right(y);
+                  }
+                else
+                  {
+                     if (y < 0.0)      show_edge_top(x);
+                     else if (y > 1.0) show_edge_bottom(x);
+                     else
+                       {
+                          hide_corners();
+                          hide_edges();
+                       }
+                  }
+             }
+          }
+       }
+       parts {
+           part { name: "clipper";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 0;
+               clip_to: "clipper";
+               description { state: "default" 0.0;
+                   min: 30 30;
+                   rel1 {
+                       to: "elm.swallow.content";
+                       offset: -15 -15;
+                   }
+                   rel2 {
+                       to: "elm.swallow.content";
+                       offset: 14 14;
+                   }
+                   image {
+                       normal: "tooltip-base.png";
+                       border: 14 14 14 14;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+
+#define TT_CORNER(name_, rx, ry, ax, ay, ox, oy)                        \
+           part { name: "corner-"name_;                                 \
+              type: IMAGE;                                              \
+              mouse_events: 0;                                          \
+              clip_to: "clipper";                                       \
+              description { state: "default" 0.0;                       \
+                 color: 255 255 255 0;                                  \
+                 visible: 0;                                            \
+                 min: 14 14;                                            \
+                 max: 14 14;                                            \
+                 align: ax ay;                                          \
+                 fixed: 1 1;                                            \
+                 rel1 {                                                 \
+                    relative: rx ry;                                    \
+                    offset: ox oy;                                      \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+                 rel2 {                                                 \
+                    relative: rx ry;                                    \
+                    offset: ox oy;                                      \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+                 image.normal: "tooltip-corner-"name_"-tip.png";        \
+              }                                                         \
+              description { state: "visible" 0.0;                       \
+                 inherit: "default" 0.0;                                \
+                 color: 255 255 255 255;                                \
+                 visible: 1;                                            \
+              }                                                         \
+           }
+           TT_CORNER("top-left", 0, 0, 1, 1, 4, 4);
+           TT_CORNER("top-right", 1, 0, 0, 1, -5, 4);
+           TT_CORNER("bottom-left", 0, 1, 1, 0, 4, -5);
+           TT_CORNER("bottom-right", 1, 1, 0, 0, -5, -5);
+#undef TT_CORNER
+
+#define TT_EDGE_VERT(name_, rx, ax, ox)                                 \
+           part { name: "clipper-edge-"name_;                           \
+              type: RECT;                                               \
+              clip_to: "clipper";                                       \
+              description { state: "default" 0.0;                       \
+                 color: 255 255 255 0;                                  \
+                 visible: 0;                                            \
+                 min: 14 14;                                            \
+                 align: ax 0.5;                                         \
+                 fixed: 1 1;                                            \
+                 rel1 {                                                 \
+                    relative: rx 0.0;                                   \
+                    offset: ox 0;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+                 rel2 {                                                 \
+                    relative: rx 1.0;                                   \
+                    offset: ox 0;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+              }                                                         \
+              description { state: "visible" 0.0;                       \
+                 inherit: "default" 0.0;                                \
+                 color: 255 255 255 255;                                \
+                 visible: 1;                                            \
+              }                                                         \
+           }                                                            \
+           part { name: "edge-area-"name_;                              \
+              type: RECT;                                               \
+              mouse_events: 0;                                          \
+              clip_to: "clipper-edge-"name_;                            \
+              description { state: "default" 0.0;                       \
+                 color: 0 0 0 0;                                        \
+                 min: 14 14;                                            \
+                 align: ax 0.5;                                         \
+                 fixed: 1 1;                                            \
+                 rel1 {                                                 \
+                    relative: rx 0.0;                                   \
+                    offset: ox 0;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+                 rel2 {                                                 \
+                    relative: rx 1.0;                                   \
+                    offset: ox 0;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+              }                                                         \
+           }                                                            \
+           part { name: "edge-drag-"name_;                              \
+              type: RECT;                                               \
+              mouse_events: 0;                                          \
+              clip_to: "clipper-edge-"name_;                            \
+              dragable {                                                \
+                  x: 0 0 0;                                             \
+                  y: 1 1 0;                                             \
+                  confine: "edge-area-"name_;                           \
+              }                                                         \
+              description { state: "default" 0.0;                       \
+                 color: 0 0 0 0;                                        \
+                 min: 14 14;                                            \
+                 rel1.to: "edge-area-"name_;                            \
+                 rel2.to: "edge-area-"name_;                            \
+              }                                                         \
+           }                                                            \
+           part { name: "edge-img-"name_;                               \
+              type: IMAGE;                                              \
+              mouse_events: 0;                                          \
+              clip_to: "clipper-edge-"name_;                            \
+              description { state: "default" 0.0;                       \
+                 min: 14 14;                                            \
+                 max: 14 14;                                            \
+                 align: ax 0.5;                                         \
+                 fixed: 1 1;                                            \
+                 rel1.to: "edge-drag-"name_;                            \
+                 rel2.to: "edge-drag-"name_;                            \
+                 image.normal: "tooltip-edge-"name_"-tip.png";          \
+              }                                                         \
+           }
+           TT_EDGE_VERT("left", 0, 1, -2);
+           TT_EDGE_VERT("right", 1, 0, 1);
+#undef TT_EDGE_VERT
+
+#define TT_EDGE_HORIZ(name_, ry, ay, oy)                                \
+           part { name: "clipper-edge-"name_;                           \
+              type: RECT;                                               \
+              clip_to: "clipper";                                       \
+              description { state: "default" 0.0;                       \
+                 color: 255 255 255 0;                                  \
+                 visible: 0;                                            \
+                 min: 14 14;                                            \
+                 align: 0.5 ay;                                         \
+                 fixed: 1 1;                                            \
+                 rel1 {                                                 \
+                    relative: 0.0 ry;                                   \
+                    offset: 0 oy;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+                 rel2 {                                                 \
+                    relative: 1.0 ry;                                   \
+                    offset: 0 oy;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+              }                                                         \
+              description { state: "visible" 0.0;                       \
+                 inherit: "default" 0.0;                                \
+                 color: 255 255 255 255;                                \
+                 visible: 1;                                            \
+              }                                                         \
+           }                                                            \
+           part { name: "edge-area-"name_;                              \
+              type: RECT;                                               \
+              mouse_events: 0;                                          \
+              clip_to: "clipper-edge-"name_;                            \
+              description { state: "default" 0.0;                       \
+                 color: 0 0 0 0;                                        \
+                 min: 14 14;                                            \
+                 align: 0.5 ay;                                         \
+                 fixed: 1 1;                                            \
+                 rel1 {                                                 \
+                    relative: 0.0 ry;                                   \
+                    offset: 0 oy;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+                 rel2 {                                                 \
+                    relative: 1.0 ry;                                   \
+                    offset: 0 oy;                                       \
+                    to: "elm.swallow.content";                          \
+                 }                                                      \
+              }                                                         \
+           }                                                            \
+           part { name: "edge-drag-"name_;                              \
+              type: RECT;                                               \
+              mouse_events: 0;                                          \
+              clip_to: "clipper-edge-"name_;                            \
+              dragable {                                                \
+                  x: 1 1 0;                                             \
+                  y: 0 0 0;                                             \
+                  confine: "edge-area-"name_;                           \
+              }                                                         \
+              description { state: "default" 0.0;                       \
+                 color: 0 0 0 0;                                        \
+                 min: 14 14;                                            \
+                 rel1.to: "edge-area-"name_;                            \
+                 rel2.to: "edge-area-"name_;                            \
+              }                                                         \
+           }                                                            \
+           part { name: "edge-img-"name_;                               \
+              type: IMAGE;                                              \
+              mouse_events: 0;                                          \
+              clip_to: "clipper-edge-"name_;                            \
+              description { state: "default" 0.0;                       \
+                 min: 14 14;                                            \
+                 max: 14 14;                                            \
+                 align: 0.5 ay;                                         \
+                 fixed: 1 1;                                            \
+                 rel1.to: "edge-drag-"name_;                            \
+                 rel2.to: "edge-drag-"name_;                            \
+                 image.normal: "tooltip-edge-"name_"-tip.png";          \
+              }                                                         \
+           }
+           TT_EDGE_HORIZ("top", 0, 1, -2);
+           TT_EDGE_HORIZ("bottom", 1, 0, 1);
+#undef TT_EDGE_HORIZ
+
+           part { name: "clipper_content";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               clip_to: "clipper_content";
+               description { state: "default" 0.0; }
+           }
+           programs {
+               program {
+                   name: "show0";
+                   signal: "elm,action,show";
+                   source: "elm";
+                   action: ACTION_STOP;
+                   target: "hide0";
+                   target: "hide1";
+                   target: "hide2";
+                   target: "hide3";
+                   after: "show1";
+                   after: "show2";
+               }
+               program {
+                   name: "show1";
+                   action: STATE_SET "visible" 0.0;
+                   transition: LINEAR 0.15;
+                   target: "clipper";
+               }
+               program {
+                   name: "show2";
+                   in: 0.1 0.0;
+                   action: STATE_SET "visible" 0.0;
+                   transition: LINEAR 0.15;
+                   target: "clipper_content";
+               }
+
+               program {
+                   name: "hide0";
+                   signal: "elm,action,hide";
+                   source: "elm";
+                   action: ACTION_STOP;
+                   target: "show0";
+                   target: "show1";
+                   target: "show2";
+                   after: "hide1";
+                   after: "hide2";
+                   after: "hide3";
+               }
+               program {
+                   name: "hide1";
+                   script {
+                      hide_corners();
+                      hide_edges();
+                   }
+               }
+               program {
+                   name: "hide2";
+                   action: STATE_SET "default" 0.0;
+                   transition: LINEAR 0.1;
+                   target: "clipper_content";
+               }
+               program {
+                   name: "hide3";
+                   in: 0.1 0.0;
+                   action: STATE_SET "default" 0.0;
+                   transition: LINEAR 0.1;
+                   target: "clipper";
+               }
+           }
+       }
+   }
+   group { name: "elm/tooltip/base/transparent";
+      parts {
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            mouse_events:   0;
+            scale: 1;
+            description { state: "default" 0.0; }
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+
+   /* TODO: replicate diagonal swallow slots to the other hover styles */
+   group { name: "elm/hover/base/default";
+      images {
+        image: "shad_circ.png" COMP;
+      }
+      parts {
+        part { name: "elm.swallow.offset";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.0;
+              rel1.relative: 0.0 0.0;
+              rel2.relative: 0.0 0.0;
+           }
+        }
+        part { name: "elm.swallow.size";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.0;
+              rel1.to: "elm.swallow.offset";
+              rel1.relative: 1.0 1.0;
+              rel2.to: "elm.swallow.offset";
+              rel2.relative: 1.0 1.0;
+           }
+        }
+        part { name: "base";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              color: 0 0 0 64;
+           }
+        }
+         part { name: "shad";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "shad_circ.png";
+              rel1.to: "elm.swallow.size";
+              rel1.offset: -32 -32;
+              rel2.to: "elm.swallow.size";
+              rel2.offset: 31 31;
+               fill.smooth: 0;
+           }
+        }
+        part { name: "box";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              rel1.to: "elm.swallow.size";
+              rel1.offset: -2 -2;
+              rel2.to: "elm.swallow.size";
+              rel2.offset: 1 1;
+           }
+        }
+        part { name: "elm.swallow.slot.left";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 1.0 0.5;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 0.0;
+              rel1.offset: -1 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 0.0 1.0;
+              rel2.offset: -1 -1;
+           }
+        }
+        part { name: "elm.swallow.slot.top-left";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 1.0 1.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 0.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 0.0 0.0;
+              rel2.offset: -1 -1;
+           }
+        }
+        part { name: "elm.swallow.slot.top";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.5 1.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 0.0;
+              rel1.offset: 0 -1;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 0.0;
+              rel2.offset: -1 -1;
+           }
+        }
+        part { name: "elm.swallow.slot.top-right";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 1.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 1.0 0.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 0.0;
+              rel2.offset: -1 -1;
+           }
+        }
+        part { name: "elm.swallow.slot.right";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.5;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 1.0 0.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: 0 -1;
+           }
+        }
+        part { name: "elm.swallow.slot.bottom-right";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 1.0 1.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -1 -1;
+           }
+        }
+        part { name: "elm.swallow.slot.bottom";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.5 0.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 1.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -1 0;
+           }
+        }
+        part { name: "elm.swallow.slot.bottom-left";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 1.0 0.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 1.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 0.0 1.0;
+              rel2.offset: -1 0;
+           }
+        }
+        part { name: "elm.swallow.slot.middle";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.size";
+              rel2.to: "elm.swallow.size";
+           }
+        }
+      }
+      programs {
+        program { name: "end";
+           signal: "mouse,up,1";
+           source: "base";
+           action: SIGNAL_EMIT "elm,action,dismiss" "";
+        }
+      }
+   }
+
+   group { name: "elm/hover/base/popout";
+      images {
+        image: "shad_circ.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+      }
+      parts {
+        part { name: "elm.swallow.offset";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.0;
+              rel1.relative: 0.0 0.0;
+              rel2.relative: 0.0 0.0;
+           }
+        }
+        part { name: "elm.swallow.size";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.0;
+              rel1.to: "elm.swallow.offset";
+              rel1.relative: 1.0 1.0;
+              rel2.to: "elm.swallow.offset";
+              rel2.relative: 1.0 1.0;
+           }
+        }
+        part { name: "base";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 1.0;
+              color: 0 0 0 64;
+           }
+        }
+        part { name: "leftclip";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel2.to_x: "pop";
+              rel2.relative: 0.0 1.0;
+               rel2.offset: 1 -1;
+           }
+        }
+        part { name: "left";
+           clip_to: "leftclip";
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to: "elm.swallow.slot.left";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.slot.left";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "elm.swallow.slot.left";
+            type: SWALLOW;
+           clip_to: "leftclip";
+           description { state: "default" 0.0;
+              align: 0.0 0.5;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 0.0;
+              rel1.offset: -1 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 0.0 1.0;
+              rel2.offset: -1 -1;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: -7 0;
+              rel2.offset: -7 -1;
+              align: 1.0 0.5;
+           }
+        }
+         part { name: "leftover";
+           clip_to: "leftclip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "left";
+              rel2.to: "left";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "rightclip";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel1.to_x: "pop";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: -2 0;
+           }
+        }
+        part { name: "right";
+           clip_to: "rightclip";
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to: "elm.swallow.slot.right";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.slot.right";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "elm.swallow.slot.right";
+            type: SWALLOW;
+           clip_to: "rightclip";
+           description { state: "default" 0.0;
+              align: 1.0 0.5;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 1.0 0.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: 0 -1;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: 6 0;
+              rel2.offset: 6 -1;
+              align: 0.0 0.5;
+           }
+        }
+         part { name: "rightover";
+           clip_to: "rightclip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "right";
+              rel2.to: "right";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "topclip";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel2.to_y: "pop";
+              rel2.relative: 1.0 0.0;
+               rel2.offset: -1 1;
+           }
+        }
+        part { name: "top";
+           clip_to: "topclip";
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to: "elm.swallow.slot.top";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.slot.top";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "elm.swallow.slot.top";
+            type: SWALLOW;
+           clip_to: "topclip";
+           description { state: "default" 0.0;
+              visible: 1;
+              align: 0.5 0.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 0.0;
+              rel1.offset: 0 -1;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 0.0;
+              rel2.offset: -1 -1;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: 0 -7;
+              rel2.offset: -1 -7;
+              align: 0.5 1.0;
+           }
+        }
+         part { name: "topover";
+           clip_to: "topclip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "top";
+              rel2.to: "top";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "bottomclip";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel1.to_y: "pop";
+              rel1.relative: 0.0 1.0;
+               rel1.offset: -1 -2;
+           }
+        }
+        part { name: "bottom";
+           clip_to: "bottomclip";
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to: "elm.swallow.slot.bottom";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.slot.bottom";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+        part { name: "elm.swallow.slot.bottom";
+            type: SWALLOW;
+           clip_to: "bottomclip";
+           description { state: "default" 0.0;
+              align: 0.5 1.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 1.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -1 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: 0 6;
+              rel2.offset: -1 6;
+              align: 0.5 0.0;
+           }
+        }
+         part { name: "bottomover";
+           clip_to: "bottomclip";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "bottom";
+              rel2.to: "bottom";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+         part { name: "shad";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "shad_circ.png";
+              rel1.to: "elm.swallow.size";
+              rel1.offset: -64 -64;
+              rel2.to: "elm.swallow.size";
+              rel2.offset: 63 63;
+               fill.smooth: 0;
+           }
+        }
+        part { name: "pop";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.slot.middle";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.slot.middle";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+        }
+        part { name: "elm.swallow.slot.middle";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.size";
+              rel2.to: "elm.swallow.size";
+           }
+        }
+         part { name: "popover";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "pop";
+              rel2.to: "pop";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+      }
+      programs {
+        program { name: "end";
+           signal: "mouse,up,1";
+           source: "base";
+           action: SIGNAL_EMIT "elm,action,dismiss" "";
+        }
+
+        program { name: "show";
+            signal: "elm,action,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+        program { name: "hide";
+            signal: "elm,action,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+
+        program { name: "leftshow";
+            signal: "elm,action,slot,left,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "left";
+           target: "elm.swallow.slot.left";
+        }
+        program { name: "lefthide";
+            signal: "elm,action,slot,left,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           transition: DECELERATE 0.5;
+           target: "left";
+           target: "elm.swallow.slot.left";
+        }
+        program { name: "rightshow";
+            signal: "elm,action,slot,right,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "right";
+           target: "elm.swallow.slot.right";
+        }
+        program { name: "righthide";
+            signal: "elm,action,slot,right,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           transition: DECELERATE 0.5;
+           target: "right";
+           target: "elm.swallow.slot.right";
+        }
+        program { name: "topshow";
+            signal: "elm,action,slot,top,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "top";
+           target: "elm.swallow.slot.top";
+        }
+        program { name: "tophide";
+            signal: "elm,action,slot,top,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           transition: DECELERATE 0.5;
+           target: "top";
+           target: "elm.swallow.slot.top";
+        }
+        program { name: "bottomshow";
+            signal: "elm,action,slot,bottom,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "bottom";
+           target: "elm.swallow.slot.bottom";
+        }
+        program { name: "bottomhide";
+            signal: "elm,action,slot,bottom,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           transition: DECELERATE 0.5;
+           target: "bottom";
+           target: "elm.swallow.slot.bottom";
+        }
+      }
+   }
+
+   //In the hover used by the menu only the bottom part is used.
+   group { name: "elm/hover/base/menu";
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+       }
+       parts {
+           part { name: "elm.swallow.offset";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   align: 0.0 0.0;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 0.0 0.0;
+               }
+           }
+           part { name: "elm.swallow.size";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   align: 0.0 0.0;
+                   rel1.to: "elm.swallow.offset";
+                   rel1.relative: 1.0 1.0;
+                   rel2.to: "elm.swallow.offset";
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "base";
+               type: RECT;
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 1.0;
+                   color: 0 0 0 64;
+               }
+           }
+           part { name: "elm.swallow.slot.left";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+               }
+           }
+           part { name: "elm.swallow.slot.right";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+               }
+           }
+           part { name: "elm.swallow.slot.top";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+               }
+           }
+           part { name: "bottomclip";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.to_y: "pop";
+                   rel1.relative: 0.0 1.0;
+                   rel1.offset: -1 -2;
+               }
+           }
+           part { name: "bottom";
+               clip_to: "bottomclip";
+               description { state: "default" 0.0;
+                   visible: 0;
+                   rel1.to: "elm.swallow.slot.bottom";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.slot.bottom";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+           }
+           part { name: "elm.swallow.slot.bottom";
+               type: SWALLOW;
+               clip_to: "bottomclip";
+               description { state: "default" 0.0;
+                   align: 0.5 1.0;
+                   rel1.to: "elm.swallow.slot.middle";
+                   rel1.relative: 0.0 1.0;
+                   rel1.offset: 0 0;
+                   rel2.to: "elm.swallow.slot.middle";
+                   rel2.relative: 1.0 1.0;
+                   rel2.offset: -1 0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   rel1.offset: 0 6;
+                   rel2.offset: -1 6;
+                   align: 0.5 0.0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               repeat_events:1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.slot.middle";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.slot.middle";
+                   rel2.offset: 4 4;
+               }
+           }
+           part { name: "elm.swallow.slot.middle";
+               type: SWALLOW;
+               repeat_events:1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.size";
+                   rel2.to: "elm.swallow.size";
+               }
+           }
+       }
+       programs {
+           program { name: "end";
+               signal: "mouse,up,1";
+               source: "base";
+               action: SIGNAL_EMIT "elm,action,dismiss" "";
+           }
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+                       //          transition: DECELERATE 0.5;
+               target: "base";
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+                       //          transition: DECELERATE 0.5;
+               target: "base";
+           }
+           program { name: "bottomshow";
+               signal: "elm,action,slot,bottom,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               transition: DECELERATE 0.3;
+               target: "bottom";
+               target: "elm.swallow.slot.bottom";
+           }
+           program { name: "bottomhide";
+               signal: "elm,action,slot,bottom,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "bottom";
+               target: "elm.swallow.slot.bottom";
+           }
+       }
+   }
+
+   //In the hover used by the submenu only the bottom part is used
+   //and no part should interact except the bottom area
+   group { name: "elm/hover/base/submenu";
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+       }
+       parts {
+           part { name: "elm.swallow.offset";
+               type: SWALLOW;
+               repeat_events:1;
+               description { state: "default" 0.0;
+                   align: 0.0 0.0;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 0.0 0.0;
+               }
+           }
+           part { name: "elm.swallow.size";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   align: 0.0 0.0;
+                   rel1.to: "elm.swallow.offset";
+                   rel1.relative: 1.0 1.0;
+                   rel2.to: "elm.swallow.offset";
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           //here we do non catch events like the hover hover does
+           part { name: "base";
+               type: RECT;
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   visible: 0;
+               }
+           }
+           part { name: "elm.swallow.slot.left";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+               }
+           }
+           part { name: "elm.swallow.slot.right";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+               }
+           }
+           part { name: "elm.swallow.slot.top";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+               }
+           }
+           part { name: "bottomclip";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.to_y: "pop";
+                   rel1.relative: 0.0 1.0;
+                   rel1.offset: -1 -2;
+               }
+           }
+           part { name: "bottom";
+               clip_to: "bottomclip";
+               description { state: "default" 0.0;
+                   visible: 0;
+                   rel1.to: "elm.swallow.slot.bottom";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.slot.bottom";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+           }
+           part { name: "elm.swallow.slot.bottom";
+               type: SWALLOW;
+               clip_to: "bottomclip";
+               description { state: "default" 0.0;
+                   align: 0.5 1.0;
+                   rel1.to: "elm.swallow.slot.middle";
+                   rel1.relative: 0.0 1.0;
+                   rel1.offset: 0 0;
+                   rel2.to: "elm.swallow.slot.middle";
+                   rel2.relative: 1.0 1.0;
+                   rel2.offset: -1 0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   rel1.offset: 0 6;
+                   rel2.offset: -1 6;
+                   align: 0.5 0.0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               repeat_events:1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.slot.middle";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.slot.middle";
+                   rel2.offset: 4 4;
+               }
+           }
+           part { name: "elm.swallow.slot.middle";
+               type: SWALLOW;
+               repeat_events:1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.size";
+                   rel2.to: "elm.swallow.size";
+               }
+           }
+       }
+       programs {
+           program { name: "end";
+               signal: "mouse,up,1";
+               source: "base";
+               action: SIGNAL_EMIT "elm,action,dismiss" "";
+           }
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+                       //          transition: DECELERATE 0.5;
+               target: "base";
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+                       //          transition: DECELERATE 0.5;
+               target: "base";
+           }
+           program { name: "bottomshow";
+               signal: "elm,action,slot,bottom,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               transition: DECELERATE 0.3;
+               target: "bottom";
+               target: "elm.swallow.slot.bottom";
+           }
+           program { name: "bottomhide";
+               signal: "elm,action,slot,bottom,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "bottom";
+               target: "elm.swallow.slot.bottom";
+           }
+       }
+   }
+
+   group { name: "elm/hover/base/hoversel_vertical/default";
+      alias: "elm/hover/base/hoversel_vertical/entry";
+      images {
+//      image: "shad_circ.png" COMP;
+        image: "bt_base2.png" COMP;
+        image: "bt_hilight.png" COMP;
+        image: "bt_shine.png" COMP;
+        image: "outdent-top.png" COMP;
+        image: "outdent-bottom.png" COMP;
+      }
+      parts {
+        part { name: "elm.swallow.offset";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.0;
+              rel1.relative: 0.0 0.0;
+              rel2.relative: 0.0 0.0;
+           }
+        }
+        part { name: "elm.swallow.size";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.0 0.0;
+              rel1.to: "elm.swallow.offset";
+              rel1.relative: 1.0 1.0;
+              rel2.to: "elm.swallow.offset";
+              rel2.relative: 1.0 1.0;
+           }
+        }
+/*
+        part { name: "shad";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "shad_circ.png";
+              rel1.to: "button_image";
+              rel1.offset: -64 -64;
+              rel2.to: "button_image";
+              rel2.offset: 63 63;
+               fill.smooth: 0;
+           }
+        }
+ */
+        part { name: "button_image";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to_x: "elm.swallow.slot.top";
+              rel1.to_y: "elm.swallow.slot.top";
+               rel1.offset: -2 -6;
+              rel2.to_x: "elm.swallow.slot.top";
+              rel2.to_y: "elm.swallow.slot.bottom";
+               rel2.offset: 1 5;
+              image {
+                 normal: "bt_base2.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "bottom" 0.0;
+              rel1.to_x: "elm.swallow.slot.bottom";
+              rel1.to_y: "elm.swallow.slot.top";
+               rel1.offset: -2 -6;
+              rel2.to_x: "elm.swallow.slot.bottom";
+              rel2.to_y: "elm.swallow.slot.bottom";
+               rel2.offset: 1 5;
+              image {
+                 normal: "bt_base2.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+        }
+
+        part { name: "base";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 1.0;
+              color: 0 0 0 64;
+           }
+        }
+
+        part { name: "topclip";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel2.to_y: "edge_top";
+              rel2.relative: 1.0 0.0;
+               rel2.offset: -1 7;
+           }
+        }
+        part { name: "elm.swallow.slot.top";
+            type: SWALLOW;
+           clip_to: "topclip";
+           description { state: "default" 0.0;
+              visible: 1;
+              align: 0.5 0.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 0.0;
+              rel1.offset: 0 -1;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 0.0;
+              rel2.offset: -1 -1;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: 0 -7;
+              rel2.offset: -1 -7;
+              align: 0.5 1.0;
+           }
+        }
+
+        part { name: "bottomclip";
+           type: RECT;
+           description { state: "default" 0.0;
+              rel1.to_y: "edge_bottom";
+              rel1.relative: 0.0 1.0;
+               rel1.offset: -1 -8;
+           }
+        }
+        part { name: "elm.swallow.slot.bottom";
+            type: SWALLOW;
+           clip_to: "bottomclip";
+           description { state: "default" 0.0;
+              align: 0.5 1.0;
+              rel1.to: "elm.swallow.slot.middle";
+              rel1.relative: 0.0 1.0;
+              rel1.offset: 0 0;
+              rel2.to: "elm.swallow.slot.middle";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -1 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              rel1.offset: 0 6;
+              rel2.offset: -1 6;
+              align: 0.5 0.0;
+           }
+        }
+
+        part {   name: "over1";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+               rel1.to: "button_image";
+               rel2.to: "button_image";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_hilight.png";
+                 border: 7 7 7 0;
+              }
+           }
+        }
+        part { name: "over2";
+           mouse_events: 1;
+           repeat_events: 1;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+               rel1.to: "button_image";
+               rel2.to: "button_image";
+              image {
+                 normal: "bt_shine.png";
+                 border: 7 7 7 7;
+              }
+           }
+        }
+         part { name: "edge_top";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+               visible: 0;
+              rel1 {
+                  to: "elm.swallow.size";
+                  offset: 0 -10;
+               }
+              rel2 {
+                  to: "elm.swallow.size";
+               }
+              image.normal: "outdent-bottom.png";
+               image.border: 0 0 13 0;
+               fill.smooth: 0;
+           }
+           description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+           }
+        }
+         part { name: "edge_bottom";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+               visible: 0;
+              rel1 {
+                  to: "elm.swallow.size";
+               }
+              rel2 {
+                  to: "elm.swallow.size";
+                  offset: -1 9;
+               }
+              image.normal: "outdent-top.png";
+               image.border: 0 0 0 13;
+               fill.smooth: 0;
+           }
+           description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+           }
+        }
+        part { name: "elm.swallow.slot.middle";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.size";
+              rel2.to: "elm.swallow.size";
+           }
+        }
+      }
+      programs {
+        program { name: "end";
+           signal: "mouse,up,1";
+           source: "base";
+           action: SIGNAL_EMIT "elm,action,dismiss" "";
+        }
+
+        program { name: "show";
+            signal: "elm,action,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+        program { name: "hide";
+            signal: "elm,action,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+        program { name: "topshow";
+            signal: "elm,action,slot,top,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           target: "edge_top";
+            after: "topshow2";
+        }
+        program { name: "topshow2";
+           action: STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "elm.swallow.slot.top";
+        }
+        program { name: "topshow3";
+            signal: "elm,action,slot,top,show";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "button_image";
+        }
+        program { name: "tophide";
+            signal: "elm,action,slot,top,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           transition: DECELERATE 0.5;
+           target: "elm.swallow.slot.top";
+            after: "tophide2";
+        }
+        program { name: "tophide2";
+           action: STATE_SET "default" 0.0;
+           target: "edge_top";
+        }
+        program { name: "bottomshow";
+            signal: "elm,action,slot,bottom,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+           target: "edge_bottom";
+            after: "bottomshow2";
+        }
+        program { name: "bottomshow2";
+           action: STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "elm.swallow.slot.bottom";
+        }
+        program { name: "bottomshow3";
+            signal: "elm,action,slot,bottom,show";
+           source: "elm";
+           action: STATE_SET "bottom" 0.0;
+           target: "button_image";
+        }
+        program { name: "bottomhide";
+            signal: "elm,action,slot,bottom,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           transition: DECELERATE 0.5;
+           target: "elm.swallow.slot.bottom";
+            after: "bottomhide2";
+        }
+        program { name: "bottomhide2";
+           action: STATE_SET "default" 0.0;
+           target: "edge_bottom";
+        }
+      }
+   }
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/scroller/base/ctxpopup";
+      data {
+         item: "focus_highlight" "on";
+      }
+      script {
+         public sbvis_v, sbvis_h, sbalways_v, sbalways_h, sbvis_timer;
+         public timer0(val) {
+            new v;
+            v = get_int(sbvis_v);
+            if (v) {
+               v = get_int(sbalways_v);
+               if(!v) {
+                  emit("do-hide-vbar", "");
+                  set_int(sbvis_v, 0);
+               }
+            }
+            v = get_int(sbvis_h);
+            if (v) {
+               v = get_int(sbalways_h);
+               if(!v) {
+                  emit("do-hide-hbar", "");
+                  set_int(sbvis_h, 0);
+               }
+            }
+            set_int(sbvis_timer, 0);
+            return 0;
+         }
+      }
+      images {
+         image: "bt_sm_base2.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "sl_bt2_2.png" COMP;
+      }
+      parts {
+         part { name: "clipper";
+            type: RECT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+            }
+         }
+         part { name: "elm.swallow.content";
+            clip_to: "clipper";
+            type: SWALLOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               align: 0.5 0.5;
+            }
+         }
+         part { name: "focus_highlight";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.offset: -1 -1;
+               rel2.offset: 0 0;
+               image { normal: "sl_bt2_2.png";
+                  border: 7 7 7 7;
+                  middle: 0;
+               }
+               fill.smooth : 0;
+               color: 200 155 0 0;
+            }
+            description { state: "enabled" 0.0;
+               inherit: "default" 0.0;
+               color: 200 155 0 255;
+            }
+         }
+         part { name: "sb_vbar_clip_master";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+            }
+         }       
+         part { name: "sb_vbar_clip";
+            clip_to:"sb_vbar_clip_master";
+            type: RECT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               rel2{ to:"clipper"; relative: 1.0 1.0;}
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+            }
+         }
+         part { name: "sb_vbar";
+            type: RECT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               visible: 0;
+               align: 1.0 0.0;
+               rel1{ to:"clipper"; relative: 1.0 0.0; }
+               rel2{ to:"clipper"; relative: 1.0 1.0; }
+            }
+         }
+         part { name: "elm.dragable.vbar";
+            clip_to: "sb_vbar_clip";
+            mouse_events: 0;    
+            scale: 1;
+            dragable {
+               x: 0 0 0;
+               y: 1 1 0;
+               confine: "sb_vbar";
+            }
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               min: 10 17;
+               max: 10 99999;
+               rel1 { relative: 0.5 0.5; to: "sb_vbar"; }
+               rel2 { relative: 0.5  0.5; to: "sb_vbar"; }
+               image { normal: "bt_sm_base2.png";
+                  border: 6 6 6 6;
+                  middle: SOLID;
+               }
+            }
+         }
+         part { name: "sb_vbar_over1";
+            clip_to: "sb_vbar_clip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.dragable.vbar";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "elm.dragable.vbar";
+               image { normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+         part { name: "sb_vbar_over2";
+            clip_to: "sb_vbar_clip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.dragable.vbar";
+               rel2.to: "elm.dragable.vbar";
+               image { normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+         part { name: "sb_hbar_clip_master";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+            }
+         }       
+         part { name: "sb_hbar_clip";
+            clip_to: "sb_hbar_clip_master";
+            type: RECT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               rel2{ to:"clipper"; relative: 1.0 1.0;}
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+            }
+         }
+         part { name: "sb_hbar";
+            type: RECT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0; 
+               fixed: 1 1;
+               visible: 0;
+               align: 0.0 1.0;
+               rel1 { to:"clipper"; relative: 0.0 1.0; }
+               rel2 { to:"clipper"; relative: 1.0 1.0; }       
+            }
+         }
+         part { name: "elm.dragable.hbar";
+            clip_to: "sb_hbar_clip";
+            mouse_events: 0;   
+            scale: 1;
+            dragable {
+               x: 1 1 0;
+               y: 0 0 0;
+               confine: "sb_hbar";
+            }
+            description { state: "default" 0.0;
+               min: 17 10;
+               max: 99999 10;
+               fixed: 1 1;
+               rel1 { relative: 0.5  0.5; to: "sb_hbar"; }
+               rel2 { relative: 0.5  0.5; to: "sb_hbar"; }
+               image { normal: "bt_sm_base2.png";
+                  border: 4 4 4 4;
+                  middle: SOLID;
+               }
+            }
+         }
+         part { name: "sb_hbar_over1";
+            clip_to: "sb_hbar_clip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.dragable.hbar";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "elm.dragable.hbar";
+               image { normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+         part { name: "sb_hbar_over2";
+            clip_to: "sb_hbar_clip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.dragable.hbar";
+               rel2.to: "elm.dragable.hbar";
+               image { normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+      }   
+      programs {
+         program { name: "load";
+            signal: "load";
+            source: "";
+            script {
+               set_state(PART:"sb_vbar_clip", "hidden", 0.0);
+               set_state(PART:"sb_hbar_clip", "hidden", 0.0);
+               set_int(sbvis_v, 0);
+               set_int(sbvis_h, 0);
+               set_int(sbalways_v, 0);
+                                  set_int(sbalways_h, 0);
+               set_int(sbvis_timer, 0);
+            }
+         } 
+         program { name: "vbar_show";
+            signal: "elm,action,show,vbar";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "sb_vbar_clip_master";
+         }
+         program { name: "vbar_hide";
+            signal: "elm,action,hide,vbar";
+            source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "sb_vbar_clip_master";
+         }       
+         program { name: "vbar_show_always";
+            signal: "elm,action,show_always,vbar";
+            source: "elm";
+            script {
+               new v;
+               v = get_int(sbvis_v);
+               v |= get_int(sbalways_v);
+               if (!v) {
+                  set_int(sbalways_v, 1);
+                  emit("do-show-vbar", "");
+                  set_int(sbvis_v, 1);
+               }
+            }
+         }
+         program { name: "vbar_show_notalways";
+            signal: "elm,action,show_notalways,vbar";
+            source: "elm";
+            script {
+               new v;
+               v = get_int(sbalways_v);
+               if (v) {
+                  set_int(sbalways_v, 0);
+                  v = get_int(sbvis_v);
+                  if (!v) {
+                     emit("do-hide-vbar", "");
+                     set_int(sbvis_v, 0);
+                  }
+               }
+            }
+         }       
+         program { name: "sb_vbar_show";
+            signal: "do-show-vbar";
+            source: "";
+            action:  STATE_SET "default" 0.0;
+            transition: LINEAR 1.0;
+            target: "sb_vbar_clip";
+         }
+         program { name: "sb_vbar_hide";
+            signal: "do-hide-vbar";
+            source: "";
+            action:  STATE_SET "hidden" 0.0;
+            transition: LINEAR 1.0;
+            target: "sb_vbar_clip";
+         }
+         program { name: "hbar_show";
+            signal: "elm,action,show,hbar";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "sb_hbar_clip_master";
+         }
+         program { name: "hbar_hide";
+            signal: "elm,action,hide,hbar";
+            source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "sb_hbar_clip_master";
+         }
+         program { name: "hbar_show_always";
+            signal: "elm,action,show_always,hbar";
+            source: "elm";
+            script {
+               new v;
+               v = get_int(sbvis_h);
+               v |= get_int(sbalways_h);
+               if (!v) {
+                  set_int(sbalways_h, 1);
+                  emit("do-show-hbar", "");
+                  set_int(sbvis_h, 1);
+               }
+            }
+         }
+         program { name: "hbar_show_notalways";
+            signal: "elm,action,show_notalways,hbar";
+            source: "elm";
+            script {
+               new v;
+               v = get_int(sbalways_h);
+               if (v) {
+                  set_int(sbalways_h, 0);
+                  v = get_int(sbvis_h);
+                  if (!v) {
+                     emit("do-hide-hbar", "");
+                     set_int(sbvis_h, 0);
+                  }
+               }
+            }
+         }
+         program { name: "sb_hbar_show";
+            signal: "do-show-hbar";
+            source: "";
+            action:  STATE_SET "default" 0.0;
+            transition: LINEAR 1.0;
+            target: "sb_hbar_clip";
+         }
+         program { name: "sb_hbar_hide";
+            signal: "do-hide-hbar";
+            source: "";
+            action:  STATE_SET "hidden" 0.0;
+            transition: LINEAR 1.0;
+            target: "sb_hbar_clip";
+         }                         
+         program { name: "scroll";
+            signal: "elm,action,scroll";
+            source: "elm";
+            script {
+               new v;
+               v = get_int(sbvis_v);
+               v |= get_int(sbalways_v);
+               if (!v) {
+                  emit("do-show-vbar", "")
+                  set_int(sbvis_v, 1);
+               }
+               v = get_int(sbvis_h);
+               v |= get_int(sbalways_h);
+               if (!v) {
+                  emit("do-show-hbar", "");
+                  set_int(sbvis_h, 1);
+               }
+               v = get_int(sbvis_timer);
+               if (v > 0) cancel_timer(v);
+               v = timer(1.0, "timer0", 0);
+               set_int(sbvis_timer, v);
+            }
+         }
+         program { name: "highlight_show";
+            signal: "elm,action,focus_highlight,show";
+            source: "elm";
+            action: STATE_SET "enabled" 0.0;
+            transition: ACCELERATE 0.3;
+            target: "focus_highlight";
+          }
+         program { name: "highlight_hide";
+            signal: "elm,action,focus_highlight,hide";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.3;
+            target: "focus_highlight";
+         }
+      }  
+   }  
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/ctxpopup/bg/default";
+      parts {
+         part { name: "ctxpopup_bg";
+            type: RECT;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 0 0 0 64;
+            }
+         }
+      }
+      programs {
+         program { name: "clicked_event";
+            signal: "mouse,clicked,1";
+            source: "ctxpopup_bg";
+            action: SIGNAL_EMIT "elm,action,click" "";
+         }
+         program { name: "show";
+            signal: "elm,state,show";
+            source: "elm";
+            action: STATE_SET "visible" 0.0;
+            target: "ctxpopup_bg";
+         }
+         program { name: "hide";
+            signal: "elm,state,hide";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "ctxpopup_bg";
+         }       
+      }
+   }
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/ctxpopup/base/default";
+      images {
+         image: "bt_base2.png" COMP;
+         image: "bt_hilight.png" COMP;
+         image: "bt_shine.png" COMP;
+      }
+      parts {
+         part { name: "base";
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1.offset: -3 -3;
+               rel2.offset: 3 3;
+               image { normal: "bt_base2.png";
+                  border: 7 7 7 7;
+               }
+            }
+         }
+         part { name: "over1";
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               rel2.relative: 1.0 0.5;
+               image { normal: "bt_hilight.png";
+                  border: 7 7 7 0;
+               }
+            }
+         }
+         part { name: "over2";
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               image { normal: "bt_shine.png";
+                  border: 7 7 7 7;
+               }
+            }
+         }
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               rel1 { to:"base"; offset: 4 4; };
+               rel2 { to:"base"; offset: -5 -5; };
+            }
+         }                      
+      } 
+   } 
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/ctxpopup/arrow/default";
+      images {
+         image: "icon_arrow_left.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_up.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts { 
+                       part { name: "ctxpopup_arrow";
+            type: IMAGE;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               min: 40 40;
+               fixed: 1 1;
+               visible: 0;
+               align: 0.5 0.5;
+            }
+            description {
+               state: "left" 0.0;
+               min: 40 40;
+               fixed: 1 1;
+               align: 0.0 0.5;
+               image { normal: "icon_arrow_left.png";
+               }
+            }
+            description { state: "right" 0.0;
+               min: 40 40;
+               fixed: 1 1;
+               align: 1.0 0.5;
+               image { normal: "icon_arrow_right.png";                
+                                       }
+            }
+            description { state: "top" 0.0;
+               min: 40 40;
+               fixed: 1 1;
+               align: 0.5 0.0;
+               image { normal: "icon_arrow_up.png";
+               }
+            }
+            description { state: "bottom" 0.0;
+               min: 40 40;
+               fixed: 1 1;
+               align: 0.5 1.0;
+               image { normal: "icon_arrow_down.png";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "enable_left_arrow";
+            signal: "elm,state,left";
+            source: "elm";
+            action: STATE_SET "left" 0.0;
+            target: "ctxpopup_arrow";
+         }
+         program { name: "enable_right_arrow";
+            signal: "elm,state,right";
+            source: "elm";
+            action: STATE_SET "right" 0.0;
+            target: "ctxpopup_arrow";
+         }
+         program { name: "enable_top_arrow";
+            signal: "elm,state,top";
+            source: "elm";
+            action: STATE_SET "top" 0.0;
+            target: "ctxpopup_arrow";
+         }
+         program { name: "enable_bottom_arrow";
+            signal: "elm,state,bottom";
+            source: "elm";
+            action: STATE_SET "bottom" 0.0;
+            target: "ctxpopup_arrow";
+         }
+      }
+   }
+///////////////////////////////////////////////////////////////////////////////
+   group { 
+      name: "elm/ctxpopup/icon_text_style_item/default";
+          alias: "elm/ctxpopup/text_style_item/default";
+          alias: "elm/ctxpopup/icon_style_item/default";
+      images {
+         image: "hoversel_entry_bg.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            mouse_events: 1;
+            description { state: "default" 0.0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.offset: 2 2;
+               rel2.offset: -3 -3;
+               image { normal:"hoversel_entry_bg.png";
+                  border: 0 0 2 2;
+               }
+               fill.smooth: 0;
+               color: 255 255 255 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0; 
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "elm.swallow.icon";
+            type: SWALLOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               min: 25 25;
+               max: 25 25;              
+               align: 0 0.5;     
+               aspect: 1.0 1.0;
+               rel1 { offset: 10 10; }              
+                                       rel2 { offset: 0 -10; }
+            }
+         }       
+         part { name: "elm.text";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               min: 1 40;
+               fixed: 0 1;
+               align: 0.5 0.5;
+               rel1 { relative: 1.0 0.0; to: "elm.swallow.icon"; offset: 10 0; }
+               rel2 { relative: 1.0 1.0; offset: -11 -1; }
+               color: 255 255 255 255;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  align: 0.0 0.5;
+                  min: 1 1;
+               }
+            }
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0;
+               color: 0 0 0 255;
+            }
+         } 
+                       part { name: "over1";
+            mouse_events: 1;
+            repeat_events: 1;
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0; 
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "over2";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0; 
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               visible: 0;
+            }
+            description { state: "enabled" 0.0;
+               visible: 1;
+               color: 50 50 50 127;
+               rel1.offset: 4 4;
+               rel2.offset: -5 -5;
+            }
+         }
+      }
+      programs {
+         program {
+            name: "item_unclick";
+            signal: "mouse,up,1";
+            source: "over1";
+            action: SIGNAL_EMIT "elm,action,click" "";
+         } 
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "enabled" 0.0;
+            target: "disclip";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "disclip";
+         }
+         program { name: "item_click2";
+            signal: "mouse,down,1";
+            source: "over2";
+            script {
+               set_state(PART:"elm.text", "clicked", 0.0);
+               set_state(PART:"bg", "clicked", 0.0);
+            }
+         }  
+         program { name: "item_unclick2";
+            signal: "mouse,up,1";
+            source: "over2";
+            script { 
+                                       set_state(PART:"elm.text", "default", 0.0);
+               set_state(PART:"bg", "default", 0.0);
+            }  
+         }
+      }   
+   }   
+///////////////////////////////////////////////////////////////////////////////
+// emoticon images from:
+// Tanya - Latvia
+// http://lazycrazy.deviantart.com/
+// http://lazycrazy.deviantart.com/art/Very-Emotional-Emoticons-144461621
+  group { name: "elm/entry/emoticon/angry/default"; images.image:
+     "emo-angry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-angry.png"; } } } }
+  group { name: "elm/entry/emoticon/angry-shout/default"; images.image:
+     "emo-angry-shout.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-angry-shout.png"; } } } }
+  group { name: "elm/entry/emoticon/crazy-laugh/default"; images.image:
+     "emo-crazy-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-crazy-laugh.png"; } } } }
+  group { name: "elm/entry/emoticon/evil-laugh/default"; images.image:
+     "emo-evil-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-evil-laugh.png"; } } } }
+  group { name: "elm/entry/emoticon/evil/default"; images.image:
+     "emo-evil.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-evil.png"; } } } }
+  group { name: "elm/entry/emoticon/goggle-smile/default"; images.image:
+     "emo-goggle-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-goggle-smile.png"; } } } }
+  group { name: "elm/entry/emoticon/grumpy/default"; images.image:
+     "emo-grumpy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-grumpy.png"; } } } }
+  group { name: "elm/entry/emoticon/grumpy-smile/default"; images.image:
+     "emo-grumpy-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-grumpy-smile.png"; } } } }
+  group { name: "elm/entry/emoticon/guilty/default"; images.image:
+     "emo-guilty.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-guilty.png"; } } } }
+  group { name: "elm/entry/emoticon/guilty-smile/default"; images.image:
+     "emo-guilty-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-guilty-smile.png"; } } } }
+  group { name: "elm/entry/emoticon/haha/default"; images.image:
+     "emo-haha.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-haha.png"; } } } }
+  group { name: "elm/entry/emoticon/half-smile/default"; images.image:
+     "emo-half-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-half-smile.png"; } } } }
+  group { name: "elm/entry/emoticon/happy-panting/default"; images.image:
+     "emo-happy-panting.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-happy-panting.png"; } } } }
+  group { name: "elm/entry/emoticon/happy/default"; images.image:
+     "emo-happy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-happy.png"; } } } }
+  group { name: "elm/entry/emoticon/indifferent/default"; images.image:
+     "emo-indifferent.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-indifferent.png"; } } } }
+  group { name: "elm/entry/emoticon/kiss/default"; images.image:
+     "emo-kiss.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-kiss.png"; } } } }
+  group { name: "elm/entry/emoticon/knowing-grin/default"; images.image:
+     "emo-knowing-grin.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-knowing-grin.png"; } } } }
+  group { name: "elm/entry/emoticon/laugh/default"; images.image:
+     "emo-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-laugh.png"; } } } }
+  group { name: "elm/entry/emoticon/little-bit-sorry/default"; images.image:
+     "emo-little-bit-sorry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-little-bit-sorry.png"; } } } }
+  group { name: "elm/entry/emoticon/love-lots/default"; images.image:
+     "emo-love-lots.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-love-lots.png"; } } } }
+  group { name: "elm/entry/emoticon/love/default"; images.image:
+     "emo-love.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-love.png"; } } } }
+  group { name: "elm/entry/emoticon/minimal-smile/default"; images.image:
+     "emo-minimal-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-minimal-smile.png"; } } } }
+  group { name: "elm/entry/emoticon/not-happy/default"; images.image:
+     "emo-not-happy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-not-happy.png"; } } } }
+  group { name: "elm/entry/emoticon/not-impressed/default"; images.image:
+     "emo-not-impressed.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-not-impressed.png"; } } } }
+  group { name: "elm/entry/emoticon/omg/default"; images.image:
+     "emo-omg.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-omg.png"; } } } }
+  group { name: "elm/entry/emoticon/opensmile/default"; images.image:
+     "emo-opensmile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-opensmile.png"; } } } }
+  group { name: "elm/entry/emoticon/smile/default"; images.image:
+     "emo-smile.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-smile.png"; } } } }
+  group { name: "elm/entry/emoticon/sorry/default"; images.image:
+     "emo-sorry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-sorry.png"; } } } }
+  group { name: "elm/entry/emoticon/squint-laugh/default"; images.image:
+     "emo-squint-laugh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-squint-laugh.png"; } } } }
+  group { name: "elm/entry/emoticon/surprised/default"; images.image:
+     "emo-surprised.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-surprised.png"; } } } }
+  group { name: "elm/entry/emoticon/suspicious/default"; images.image:
+     "emo-suspicious.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-suspicious.png"; } } } }
+  group { name: "elm/entry/emoticon/tongue-dangling/default"; images.image:
+     "emo-tongue-dangling.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-tongue-dangling.png"; } } } }
+  group { name: "elm/entry/emoticon/tongue-poke/default"; images.image:
+     "emo-tongue-poke.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-tongue-poke.png"; } } } }
+  group { name: "elm/entry/emoticon/uh/default"; images.image:
+     "emo-uh.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-uh.png"; } } } }
+  group { name: "elm/entry/emoticon/unhappy/default"; images.image:
+     "emo-unhappy.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-unhappy.png"; } } } }
+  group { name: "elm/entry/emoticon/very-sorry/default"; images.image:
+     "emo-very-sorry.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-very-sorry.png"; } } } }
+  group { name: "elm/entry/emoticon/what/default"; images.image:
+     "emo-what.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-what.png"; } } } }
+  group { name: "elm/entry/emoticon/wink/default"; images.image:
+     "emo-wink.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-wink.png"; } } } }
+  group { name: "elm/entry/emoticon/worried/default"; images.image:
+     "emo-worried.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-worried.png"; } } } }
+  group { name: "elm/entry/emoticon/wtf/default"; images.image:
+     "emo-wtf.png" COMP; parts { part { name: "icon"; mouse_events: 0; description { state: "default" 0.0; max: 64 64; image.normal:
+        "emo-wtf.png"; } } } }
+//------------------------------------------------------------
+   group { name: "elm/entry/base/default";
+      styles
+      {
+         style { name: "entry_textblock_style";
+            base: "font=Sans font_size=10 color=#000 wrap=word text_class=entry";
+            tag:  "br" "\n";
+            tag:  "ps" "ps";
+            tag:  "tab" "\t";
+            tag:  "em" "+ font=Sans:style=Oblique";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "link" "+ color=#800 underline=on underline_color=#8008";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+         }
+         style { name: "entry_textblock_disabled_style";
+            base: "font=Sans font_size=10 color=#00000080 wrap=word text_class=entry";
+            tag:  "br" "\n";
+            tag:  "ps" "ps";
+            tag:  "tab" "\t";
+            tag:  "em" "+ font=Sans:style=Oblique";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "link" "+ color=#00000080 underline=on underline_color=#00000080";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+         }
+      }
+      data {
+//         item: context_menu_orientation "horizontal";
+      }
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: EDITABLE;
+            select_mode: EXPLICIT;
+            multiline: 1;
+            source: "elm/entry/selection/default"; // selection under
+   //       source2: "X"; // selection over
+   //       source3: "X"; // cursor under
+            source4: "elm/entry/cursor/default"; // cursorover
+            source5: "elm/entry/anchor/default"; // anchor under
+   //       source6: "X"; // anchor over
+            description { state: "default" 0.0;
+               /* we gotta use 0 0 here, because of scrolled entries */
+               fixed: 0 0;
+               text {
+                  style: "entry_textblock_style";
+                  min: 0 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_textblock_disabled_style";
+                  min: 0 1;
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/base-charwrap/default";
+      styles
+      {
+         style { name: "entry_textblock_style_charwrap";
+            base: "font=Sans font_size=10 color=#000 wrap=char text_class=entry";
+            tag:  "br" "\n";
+            tag:  "ps" "ps";
+            tag:  "tab" "\t";
+            tag:  "em" "+ font=Sans:style=Oblique";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "link" "+ color=#800 underline=on underline_color=#8008";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+         }
+         style { name: "entry_textblock_disabled_style_charwrap";
+            base: "font=Sans font_size=10 color=#00000080 wrap=char text_class=entry";
+            tag:  "br" "\n";
+            tag:  "ps" "ps";
+            tag:  "tab" "\t";
+            tag:  "em" "+ font=Sans:style=Oblique";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "link" "+ color=#00000080 underline=on underline_color=#00000080";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+         }
+      }
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: EDITABLE;
+            select_mode: EXPLICIT;
+            multiline: 1;
+            source: "elm/entry/selection/default"; // selection under
+//          source2: "X"; // selection over
+//          source3: "X"; // cursor under
+            source4: "elm/entry/cursor/default"; // cursorover
+            source5: "elm/entry/anchor/default"; // anchor under
+//          source6: "X"; // anchor over
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               text {
+                  style: "entry_textblock_style_charwrap";
+                  min: 0 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_textblock_disabled_style_charwrap";
+                  min: 0 1;
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/base-nowrap/default";
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: EDITABLE;
+            select_mode: EXPLICIT;
+            multiline: 1;
+            source: "elm/entry/selection/default"; // selection under
+            source4: "elm/entry/cursor/default"; // cursorover
+            source5: "elm/entry/anchor/default"; // anchor under
+            description { state: "default" 0.0;
+               text {
+                  style: "entry_textblock_style";
+                  min: 1 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_textblock_disabled_style";
+                  min: 0 1;
+               }
+            }
+         }
+/*
+         part { name: "sel";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               align: 1.0 1.0;
+               max: 16 16;
+               aspect: 1.0 1.0;
+               color: 255 0 0 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 0 0 50;
+            }
+         }
+ */
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+/*
+         program { name: "selmode0";
+            signal: "elm,state,select,on";
+            source: "elm";
+            action: STATE_SET "visible" 0.0;
+            target: "sel";
+         }
+         program { name: "selmode1";
+            signal: "elm,state,select,off";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "sel";
+         }
+ */
+      }
+   }
+
+   group { name: "elm/entry/base-single/default";
+      styles
+      {
+         style { name: "entry_single_textblock_style";
+            base: "font=Sans font_size=10 color=#000 wrap=none text_class=entry";
+            tag:  "br" "\n";
+            tag:  "ps" "ps";
+            tag:  "tab" "\t";
+            tag:  "em" "+ font=Sans:style=Oblique";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "link" "+ color=#800 underline=on underline_color=#8008";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+         }
+         style { name: "entry_single_textblock_disabled_style";
+            base: "font=Sans font_size=10 color=#00000080 wrap=none text_class=entry";
+            tag:  "br" "\n";
+            tag:  "ps" "ps";
+            tag:  "tab" "\t";
+            tag:  "em" "+ font=Sans:style=Oblique";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "link" "+ color=#00000080 underline=on underline_color=#00000080";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+         }
+      }
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: EDITABLE;
+            select_mode: EXPLICIT;
+            multiline: 0;
+            source: "elm/entry/selection/default"; // selection under
+            source4: "elm/entry/cursor/default"; // cursorover
+            source5: "elm/entry/anchor/default"; // anchor under
+            description { state: "default" 0.0;
+               text {
+                  style: "entry_single_textblock_style";
+                  min: 1 1;
+                  max: 0 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_single_textblock_disabled_style";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/base-single-noedit/default";
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: PLAIN;
+            select_mode: EXPLICIT;
+            multiline: 0;
+            source: "elm/entry/selection/default"; // selection under
+            source5: "elm/entry/anchor/default"; // anchor under
+            description { state: "default" 0.0;
+               text {
+                  style: "entry_single_textblock_style";
+                  min: 1 1;
+                  max: 0 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+               style: "entry_single_textblock_disabled_style";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/base-noedit/default";
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: PLAIN;
+            select_mode: EXPLICIT;
+            multiline: 1;
+            source: "elm/entry/selection/default"; // selection under
+            source5: "elm/entry/anchor/default"; // anchor under
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               text {
+                  style: "entry_textblock_style";
+                  min: 0 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_textblock_disabled_style";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/base-noedit-charwrap/default";
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: PLAIN;
+            select_mode: EXPLICIT;
+            multiline: 1;
+            source: "elm/entry/selection/default"; // selection under
+            source5: "elm/entry/anchor/default"; // anchor under
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               text {
+                  style: "entry_textblock_style_charwrap";
+                  min: 0 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_textblock_disabled_style_charwrap";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/base-nowrap-noedit/default";
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: PLAIN;
+            select_mode: EXPLICIT;
+            multiline: 1;
+            source: "elm/entry/selection/default"; // selection under
+            source5: "elm/entry/anchor/default"; // anchor under
+            description { state: "default" 0.0;
+               text {
+                  style: "entry_textblock_style";
+                  min: 1 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_textblock_disabled_style";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/base-password/default";
+      parts {
+         part { name: "elm.text";
+            type: TEXTBLOCK;
+            mouse_events: 1;
+            scale: 1;
+            entry_mode: PASSWORD;
+            select_mode: EXPLICIT;
+            multiline: 0;
+            source: "elm/entry/selection/default"; // selection under
+            source4: "elm/entry/cursor/default"; // cursorover
+            source5: "elm/entry/anchor/default"; // anchor under
+            description { state: "default" 0.0;
+               text {
+                  style: "entry_single_textblock_style";
+                  repch: "*";
+                  min: 1 1;
+                  max: 0 1;
+               }
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "entry_single_textblock_disabled_style";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "focus";
+            signal: "load";
+            source: "";
+            action: FOCUS_SET;
+            target: "elm.text";
+         }
+         program { name: "disable";
+            signal: "elm,state,disabled";
+            source: "elm";
+            action: STATE_SET "disabled" 0.0;
+            target: "elm.text";
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+      }
+   }
+
+   group { name: "elm/entry/cursor/default";
+      images {
+         image: "cur_box.png" COMP;
+         image: "cur_hi.png" COMP;
+         image: "cur_shad.png" COMP;
+         image: "cur_shine.png" COMP;
+         image: "cur_glow.png" COMP;
+      }
+      parts {
+         part { name: "clip2";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "clip";
+               rel2.to: "clip";
+               visible: 0;
+            }
+            description { state: "focused" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+         }
+         part { name: "clip";
+            type: RECT;
+            mouse_events: 0;
+            clip_to: "clip2";
+            description { state: "default" 0.0;
+               rel1.offset: -10 0;
+               rel2.offset: 9 9;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel1.offset: -2 0;
+               rel2.to: "base";
+               rel2.offset: 1 1;
+               image.border: 2 2 2 2;
+               image.normal: "cur_shad.png";
+            }
+         }
+         part { name: "base";
+            mouse_events: 0;
+            scale: 1;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               min: 2 2;
+               align: 0.5 1.0;
+               rel1.relative: 0.0 1.0;
+               rel1.offset: 0 -1;
+               rel2.relative: 1.0 1.0;
+               rel2.offset: -1 -1;
+               image.normal: "cur_box.png";
+            }
+         }
+         part { name: "hi";
+            mouse_events: 0;
+            clip_to: "clip";
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               rel2.relative: 1.0 0.5;
+               image.normal: "cur_hi.png";
+            }
+         }
+         part { name: "shine";
+            mouse_events: 0;
+            clip_to: "clip";
+            clip_to: "clip2";
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               rel2.relative: 1.0 0.75;
+               image.border: 2 2 1 0;
+               image.normal: "cur_shine.png";
+               fill.smooth: 0;
+            }
+         }
+         part { name: "glow";
+            mouse_events: 0;
+            clip_to: "clip2";
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel1.relative: 0.0 -2.0;
+               rel1.offset: -2 0;
+               rel2.to: "base";
+               rel2.relative: 1.0 0.0;
+               rel2.offset: 1 1;
+               image.border: 2 2 0 4;
+               image.normal: "cur_glow.png";
+               fill.smooth: 0;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 0;
+            }
+         }
+      }
+      programs {
+         program { name: "show";
+            signal: "show";
+            source: "";
+            action: STATE_SET "hidden" 0.0;
+            in: 1.0 0.0;
+            transition: DECELERATE 2.0;
+            target: "glow";
+            after: "show2";
+         }
+         program { name: "show2";
+            action: STATE_SET "hidden" 0.0;
+            in: 0.2 0.0;
+            target: "clip";
+            after: "show3";
+         }
+         program { name: "show3";
+            action: STATE_SET "default" 0.0;
+            in: 0.5 0.0;
+            target: "clip";
+            after: "show4";
+         }
+         program { name: "show4";
+            action: STATE_SET "default" 0.0;
+            in: 0.5 0.0;
+            transition: DECELERATE 0.5;
+            target: "glow";
+            after: "show";
+         }
+         program { name: "focused";
+            signal: "elm,action,focus";
+            source: "elm";
+            action: STATE_SET "focused" 0.0;
+            target: "clip2";
+         }
+         program { name: "unfocused";
+            signal: "elm,action,unfocus";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "clip2";
+         }
+      }
+   }
+
+   group { name: "elm/entry/selection/default";
+      parts {
+         part { name: "bg";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               color: 128 128 128 128;
+            }
+         }
+      }
+   }
+
+   group { name: "elm/entry/anchor/default";
+      parts {
+         part { name: "bg";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               color: 128 0 0 64;
+            }
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+  group { name: "elm/bubble/top_left/default";
+    alias: "elm/bubble/base/default";
+    images {
+      image: "bubble_3.png" COMP;
+      image: "bubble_shine3.png" COMP;
+    }
+    parts {
+      part { name: "event";
+         type: RECT;
+         description {
+            state: "default" 0.0;
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "elm.swallow.icon";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          fixed: 1 1;
+          visible: 0;
+          align: 0.0 0.0;
+          aspect: 1.0 1.0;
+          aspect_preference: VERTICAL;
+          rel1 {
+            relative: 0.0 0.0;
+            offset: 4 4;
+          }
+          rel2 {
+            to_y: "elm.text";
+            relative: 0.0 1.0;
+            offset: 4 -1;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+        }
+      }
+      part { name: "elm.text";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 0.0 0.0;
+          fixed: 0 1;
+          visible: 0;
+          rel1 {
+            to_x: "elm.swallow.icon";
+            relative: 1.0 0.0;
+            offset: 4 4;
+          }
+          rel2 {
+            to_x: "elm.info";
+            relative: 0.0 0.0;
+            offset: -5 4;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 255;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 0 1;
+            max: 0 1;
+            align: 0.0 0.0;
+          }
+        } 
+      }
+      part { name: "elm.info";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 1.0 0.0;
+          fixed: 1 1;
+          visible: 0;
+          rel1 {
+            relative: 1.0 0.0;
+            offset: -5 4;
+          }
+          rel2 {
+            relative: 1.0 0.0;
+            offset: -5 4;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 64;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 1 1;
+            max: 1 1;
+            align: 1.0 0.0;
+          }
+        } 
+      }
+      part { name: "base0";
+        mouse_events:  0;
+        description { state: "default" 0.0;
+          rel1 {
+            to_y: "elm.swallow.icon";
+            relative: 0.0 1.0;
+            offset: 0 0;
+          }
+          image {
+            normal: "bubble_3.png";
+            border: 36 11 18 9;
+          }
+          image.middle: SOLID;
+          fill.smooth: 0;
+        }
+        description { state: "infobase" 0.0;
+          inherit: "default" 0.0;
+          rel1.to_y: "elm.info";
+        }
+      }
+      part { name: "elm.swallow.content";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 9 16;
+          }
+          rel2 {
+            to: "base0";
+            offset: -10 -9;
+          }
+        }
+      }
+      part { name: "shine";
+        mouse_events:  0;
+        description { state:    "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 5 4;
+          }
+          rel2 {
+            to: "base0";
+            relative: 1.0 0.5;
+            offset: -6 7;
+          }
+          image {
+            normal: "bubble_shine3.png";
+            border: 36 5 14 0;
+          }
+          fill.smooth: 0;
+        }
+      }
+    }
+    programs {
+      program {
+        name: "icon_show";
+        signal: "elm,state,icon,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"base0", st, 30, vl);
+          if (!strcmp(st, "infobase"))
+            set_state(PART:"base0", "default", 0.0);
+          set_state(PART:"elm.swallow.icon", "visible", 0.0);
+        }
+      }
+      program {
+        name: "icon_hide";
+        signal: "elm,state,icon,hidden";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.info", st, 30, vl);
+          if (!strcmp(st, "visible"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.swallow.icon", "default", 0.0);
+        }
+      }
+      program {
+        name: "text_show";
+        signal: "elm,state,text,visible";
+        source: "elm";
+        action: STATE_SET "visible" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "text_hide";
+        signal: "elm,state,text,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "info_show";
+        signal: "elm,state,info,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.swallow.icon", st, 30, vl);
+          if (!strcmp(st, "default"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.info", "visible", 0.0);
+        }
+      }
+      program {
+        name: "info_hide";
+        signal: "elm,state,info,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.info";
+        target: "base0";
+      }
+    }
+  }
+
+  group { name: "elm/bubble/top_right/default";
+    images {
+      image: "bubble_4.png" COMP;
+      image: "bubble_shine4.png" COMP;
+    }
+    parts {
+      part { name: "event";
+         type: RECT;
+         description {
+            state: "default" 0.0;
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "elm.swallow.icon";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          fixed: 1 1;
+          visible: 0;
+          align: 1.0 0.0;
+          aspect: 1.0 1.0;
+          aspect_preference: VERTICAL;
+          rel1 {
+            relative: 1.0 0.0;
+            offset: -5 4;
+          }
+          rel2 {
+            to_y: "elm.text";
+            relative: 1.0 1.0;
+            offset: -5 -1;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+        }
+      }
+      part { name: "elm.text";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 0.0 0.0;
+          fixed: 0 1;
+          visible: 0;
+          rel1 {
+            relative: 0.0 0.0;
+            offset: 4 4;
+          }
+          rel2 {
+            to_x: "elm.info";
+            relative: 0.0 0.0;
+            offset: -5 4;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 255;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 0 1;
+            max: 0 1;
+            align: 0.0 0.0;
+          }
+        }
+      }
+      part { name: "elm.info";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 1.0 0.0;
+          fixed: 1 1;
+          visible: 0;
+          rel1 {
+            relative: 1.0 0.0;
+            offset: -5 4;
+          }
+          rel2 {
+            to_x: "elm.swallow.icon";
+            relative: 0.0 0.0;
+            offset: -5 4;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 64;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 1 1;
+            max: 1 1;
+            align: 1.0 0.0;
+          }
+        }
+      }
+      part { name: "base0";
+        mouse_events:  0;
+        description { state: "default" 0.0;
+          rel1 {
+            to_y: "elm.swallow.icon";
+            relative: 0.0 1.0;
+            offset: 0 0;
+          }
+          image {
+            normal: "bubble_4.png";
+            border: 11 36 18 9;
+          }
+          image.middle: SOLID;
+          fill.smooth: 0;
+        }
+        description { state: "infobase" 0.0;
+          inherit: "default" 0.0;
+          rel1.to_y: "elm.info";
+        }
+      }
+      part { name: "elm.swallow.content";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 9 16;
+          }
+          rel2 {
+            to: "base0";
+            offset: -10 -9;
+          }
+        }
+      }
+      part { name: "shine";
+        mouse_events:  0;
+        description { state:    "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 5 4;
+          }
+          rel2 {
+            to: "base0";
+            relative: 1.0 0.5;
+            offset: -6 7;
+          }
+          image {
+            normal: "bubble_shine4.png";
+            border: 5 36 14 0;
+          }
+          fill.smooth: 0;
+        }
+      }
+    }
+    programs {
+      program {
+        name: "icon_show";
+        signal: "elm,state,icon,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"base0", st, 30, vl);
+          if (!strcmp(st, "infobase"))
+            set_state(PART:"base0", "default", 0.0);
+          set_state(PART:"elm.swallow.icon", "visible", 0.0);
+        }
+      }
+      program {
+        name: "icon_hide";
+        signal: "elm,state,icon,hidden";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.info", st, 30, vl);
+          if (!strcmp(st, "visible"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.swallow.icon", "default", 0.0);
+        }
+      }
+      program {
+        name: "text_show";
+        signal: "elm,state,text,visible";
+        source: "elm";
+        action: STATE_SET "visible" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "text_hide";
+        signal: "elm,state,text,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "info_show";
+        signal: "elm,state,info,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.swallow.icon", st, 30, vl);
+          if (!strcmp(st, "default"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.info", "visible", 0.0);
+        }
+      }
+      program {
+        name: "info_hide";
+        signal: "elm,state,info,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.info";
+        target: "base0";
+      }
+    }
+  }
+
+  group { name: "elm/bubble/bottom_left/default";
+    images {
+      image: "bubble_1.png" COMP;
+      image: "bubble_shine.png" COMP;
+    }
+    parts {
+      part { name: "event";
+         type: RECT;
+         description {
+            state: "default" 0.0;
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "elm.swallow.icon";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          fixed: 1 1;
+          visible: 0;
+          align: 0.0 1.0;
+          aspect: 1.0 1.0;
+          aspect_preference: VERTICAL;
+          rel1 {
+            to_y: "elm.text";
+            relative: 0.0 0.0;
+            offset: 4 0;
+          }
+          rel2 {
+            relative: 0.0 1.0;
+            offset: 4 -5;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+        }
+      }
+      part { name: "elm.text";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 0.0 1.0;
+          fixed: 0 1;
+          visible: 0;
+          rel1 {
+            to_x: "elm.swallow.icon";
+            relative: 1.0 1.0;
+            offset: 4 -5;
+          }
+          rel2 {
+            to_x: "elm.info";
+            relative: 0.0 1.0;
+            offset: -5 -5;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 255;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 0 1;
+            max: 0 1;
+            align: 0.0 1.0;
+          }
+        }
+      }
+      part { name: "elm.info";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 1.0 1.0;
+          fixed: 1 1;
+          visible: 0;
+          rel1 {
+            relative: 1.0 1.0;
+            offset: -5 -5;
+          }
+          rel2 {
+            relative: 1.0 1.0;
+            offset: -5 -5;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 64;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 1 1;
+            max: 1 1;
+            align: 1.0 1.0;
+          }
+        }
+      }
+      part { name: "base0";
+        mouse_events:  0;
+        description { state: "default" 0.0;
+          rel2 {
+            to_y: "elm.swallow.icon";
+            relative: 1.0 0.0;
+            offset: -1 -1;
+          }
+          image {
+            normal: "bubble_1.png";
+            border: 36 11 10 19;
+          }
+          image.middle: SOLID;
+          fill.smooth: 0;
+        }
+        description { state: "infobase" 0.0;
+          inherit: "default" 0.0;
+          rel2.to_y: "elm.info";
+        }
+      }
+      part { name: "elm.swallow.content";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 9 8;
+          }
+          rel2 {
+            to: "base0";
+            offset: -10 -17;
+          }
+        }
+      }
+      part { name: "shine";
+        mouse_events:  0;
+        description { state:    "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 5 4;
+          }
+          rel2 {
+            to: "base0";
+            relative: 1.0 0.5;
+            offset: -6 -16;
+          }
+          image {
+            normal: "bubble_shine.png";
+            border: 5 5 5 0;
+          }
+          fill.smooth: 0;
+        }
+      }
+    }
+    programs {
+      program {
+        name: "icon_show";
+        signal: "elm,state,icon,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"base0", st, 30, vl);
+          if (!strcmp(st, "infobase"))
+            set_state(PART:"base0", "default", 0.0);
+          set_state(PART:"elm.swallow.icon", "visible", 0.0);
+        }
+      }
+      program {
+        name: "icon_hide";
+        signal: "elm,state,icon,hidden";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.info", st, 30, vl);
+          if (!strcmp(st, "visible"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.swallow.icon", "default", 0.0);
+        }
+      }
+      program {
+        name: "text_show";
+        signal: "elm,state,text,visible";
+        source: "elm";
+        action: STATE_SET "visible" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "text_hide";
+        signal: "elm,state,text,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "info_show";
+        signal: "elm,state,info,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.swallow.icon", st, 30, vl);
+          if (!strcmp(st, "default"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.info", "visible", 0.0);
+        }
+      }
+      program {
+        name: "info_hide";
+        signal: "elm,state,info,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.info";
+        target: "base0";
+      }
+    }
+  }
+
+  group { name: "elm/bubble/bottom_right/default";
+    images {
+      image: "bubble_2.png" COMP;
+      image: "bubble_shine.png" COMP;
+    }
+    parts {
+      part { name: "event";
+         type: RECT;
+         description {
+            state: "default" 0.0;
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "elm.swallow.icon";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          fixed: 1 1;
+          visible: 0.0;
+          align: 1.0 1.0;
+          aspect: 1.0 1.0;
+          aspect_preference: VERTICAL;
+          rel1 {
+            to_y: "elm.text";
+            relative: 1.0 0.0;
+            offset: -5 0;
+          }
+          rel2 {
+            relative: 1.0 1.0;
+            offset: -5 -5;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+        }
+      }
+      part { name: "elm.text";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 0.0 1.0;
+          fixed: 0 1;
+          visible: 0;
+          rel1 {
+            relative: 0.0 1.0;
+            offset: 4 -5;
+          }
+          rel2 {
+            to_x: "elm.info";
+            relative: 0.0 1.0;
+            offset: -5 -5;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 255;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 0 1;
+            max: 0 1;
+            align: 0.0 1.0;
+          }
+        }
+      }
+      part { name: "elm.info";
+        type: TEXT;
+        mouse_events:   0;
+        scale: 1;
+        description { state: "default" 0.0;
+          align: 1.0 1.0;
+          fixed: 1 1;
+          visible: 0;
+          rel1 {
+            relative: 1.0 1.0;
+            offset: -5 -5;
+          }
+          rel2 {
+            to_x: "elm.swallow.icon";
+            relative: 0.0 1.0;
+            offset: -5 -5;
+          }
+        }
+        description { state: "visible" 0.0;
+          inherit: "default" 0.0;
+          visible: 1;
+          color: 0 0 0 64;
+          text {
+            font: "Sans:style=Bold,Edje-Vera-Bold";
+            size: 10;
+            min: 1 1;
+            max: 1 1;
+            align: 1.0 1.0;
+          }
+        }
+      }
+      part { name: "base0";
+        mouse_events:  0;
+        description { state: "default" 0.0;
+          rel2 {
+            to_y: "elm.swallow.icon";
+            relative: 1.0 0.0;
+            offset: -1 -1;
+          }
+          image {
+            normal: "bubble_2.png";
+            border: 11 36 10 19;
+          }
+          image.middle: SOLID;
+          fill.smooth: 0;
+        }
+        description { state: "infobase" 0.0;
+          inherit: "default" 0.0;
+          rel2.to_y: "elm.info";
+        }
+      }
+      part { name: "elm.swallow.content";
+        type: SWALLOW;
+        description { state: "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 9 8;
+          }
+          rel2 {
+            to: "base0";
+            offset: -10 -17;
+          }
+        }
+      }
+      part { name: "shine";
+        mouse_events:  0;
+        description { state:    "default" 0.0;
+          rel1 {
+            to: "base0";
+            offset: 5 4;
+          }
+          rel2 {
+            to: "base0";
+            relative: 1.0 0.5;
+            offset: -6 -16;
+          }
+          image {
+            normal: "bubble_shine.png";
+            border: 5 5 5 0;
+          }
+          fill.smooth: 0;
+        }
+      }
+    }
+    programs {
+      program {
+        name: "icon_show";
+        signal: "elm,state,icon,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"base0", st, 30, vl);
+          if (!strcmp(st, "infobase"))
+            set_state(PART:"base0", "default", 0.0);
+          set_state(PART:"elm.swallow.icon", "visible", 0.0);
+        }
+      }
+      program {
+        name: "icon_hide";
+        signal: "elm,state,icon,hidden";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.info", st, 30, vl);
+          if (!strcmp(st, "visible"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.swallow.icon", "default", 0.0);
+        }
+      }
+      program {
+        name: "text_show";
+        signal: "elm,state,text,visible";
+        source: "elm";
+        action: STATE_SET "visible" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "text_hide";
+        signal: "elm,state,text,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.text";
+      }
+      program {
+        name: "info_show";
+        signal: "elm,state,info,visible";
+        source: "elm";
+        script {
+          new st[31];
+          new Float:vl;
+          get_state(PART:"elm.swallow.icon", st, 30, vl);
+          if (!strcmp(st, "default"))
+            set_state(PART:"base0", "infobase", 0.0);
+          set_state(PART:"elm.info", "visible", 0.0);
+        }
+      }
+      program {
+        name: "info_hide";
+        signal: "elm,state,info,hidden";
+        source: "elm";
+        action: STATE_SET "default" 0.0;
+        target: "elm.info";
+        target: "base0";
+      }
+    }
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/photo/base/default";
+      images {
+        image: "frame_1.png" COMP;
+        image: "frame_2.png" COMP;
+         image: "dia_grad.png" COMP;
+         image: "head.png" COMP;
+      }
+      parts {
+         part { name: "base0";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "dia_grad.png";
+              rel1.to: "over";
+              rel2.to: "over";
+               fill {
+                 smooth: 0;
+                 size {
+                    relative: 0.0 1.0;
+                     offset: 64 0;
+                 }
+              }
+           }
+        }
+        part { name: "base";
+           mouse_events:  0;
+           description { state:    "default" 0.0;
+              image {
+                 normal: "frame_2.png";
+                 border: 5 5 32 26;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+        }
+         part { name: "head";
+           mouse_events:  0;
+           description { state:    "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+               aspect: 1.0 1.0;
+               aspect_preference: BOTH;
+              image.normal: "head.png";
+           }
+        }
+         part { name: "clip";
+           mouse_events:  0;
+            type: RECT;
+           description { state:    "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+               color: 255 255 255 255;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+           }
+        }
+         part { name: "over";
+           mouse_events:  0;
+           description { state:    "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+              image {
+                 normal: "frame_1.png";
+                 border: 2 2 28 22;
+                 middle: 0;
+              }
+              fill.smooth: 0;
+           }
+        }
+     }
+   }
+   
+   group { name: "elm/photo/base/shadow";
+       images {
+                       image: "shadow.png" COMP;
+                       image: "black.png" COMP;
+       }
+       script {
+       public message(Msg_Type:type, id, ...) {
+               if( (type==MSG_INT_SET) && (id==0) )
+               {
+               new w;
+               new h;
+           
+               custom_state(PART:"size", "default", 0.0);
+
+               w = getarg(2);
+               h = getarg(3);
+               set_state_val(PART:"size", STATE_REL1_OFFSET, - w/2, - h/2);
+               set_state_val(PART:"size", STATE_REL2_OFFSET, w/2 + 1, h/2 + 1);
+               set_state(PART:"size", "custom", 0.0);
+               }
+       }
+       }
+       parts {
+       part { name: "size";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                       rel1.relative: 0.5 0.5;
+                       rel2.relative: 0.5 0.5;
+               }
+               }
+       part {
+               name: "shadow";
+               type: IMAGE;
+               repeat_events: 1;
+               description {
+               state: "default" 0.0;
+               rel1.to: "size";
+               rel2.to: "size";
+               rel1.relative: -0.06 -0.06;
+               rel2.relative: 1.07 1.07;
+               image.normal: "shadow.png";
+               }
+       }
+       
+       
+               part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+               rel1.offset: 3 3;
+               rel2.offset: -3 -3;
+                       fixed: 1 1;
+               }
+               }
+               
+               part {
+               name: "border";
+               type: IMAGE;
+               repeat_events: 1;
+               description {
+               state: "default" 0.0;
+               visible: 1;
+               color: 0 0 0 255;
+               rel1.to: "size";
+               rel2.to: "size";
+               image.normal: "black.png";
+               image.border: 1 1 1 1;
+               image.middle: 0;
+               }
+       }
+               }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/thumb/base/default";
+      images {
+        image: "frame_1.png" COMP;
+        image: "frame_2.png" COMP;
+        image: "dia_grad.png" COMP;
+        image: "busy-1.png" COMP;
+        image: "busy-2.png" COMP;
+        image: "busy-3.png" COMP;
+        image: "busy-4.png" COMP;
+        image: "busy-5.png" COMP;
+        image: "busy-6.png" COMP;
+        image: "busy-7.png" COMP;
+        image: "busy-8.png" COMP;
+        image: "busy-9.png" COMP;
+      }
+      parts {
+        part { name: "base0";
+           mouse_events:  0;
+           description { state:        "default" 0.0;
+              image.normal: "dia_grad.png";
+              rel1.to: "over";
+              rel2.to: "over";
+              fill {
+                 smooth: 0;
+                 size {
+                    relative: 0.0 1.0;
+                    offset: 64 0;
+                 }
+              }
+           }
+        }
+        part { name: "base";
+           mouse_events:  0;
+           description { state:        "default" 0.0;
+              image {
+                 normal: "frame_2.png";
+                 border: 5 5 32 26;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+        }
+        part { name: "clip";
+           mouse_events:  0;
+           type: RECT;
+           description { state:        "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+              color: 255 255 255 255;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           clip_to: "clip";
+           description { state:        "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+           }
+        }
+        part { name: "progress";
+           mouse_events: 0;
+
+           clip_to: "clip";
+           description { state:        "default" 0.0;
+              min: 32 32;
+              max: 32 32;
+              visible: 0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+           }
+           description { state:        "pulse" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              image {
+                 normal: "busy-9.png";
+                 tween:  "busy-1.png";
+                 tween:  "busy-2.png";
+                 tween:  "busy-3.png";
+                 tween:  "busy-4.png";
+                 tween:  "busy-5.png";
+                 tween:  "busy-6.png";
+                 tween:  "busy-7.png";
+                 tween:  "busy-8.png";
+                 border: 7 7 7 7;
+              }
+           }
+        }
+        part { name: "over";
+           mouse_events:  0;
+           description { state:        "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+              image {
+                 normal: "frame_1.png";
+                 border: 2 2 28 22;
+                 middle: 0;
+              }
+              fill.smooth: 0;
+           }
+        }
+        programs {
+           program { name: "start_pulse";
+              signal: "elm,state,pulse,start";
+              source: "elm";
+              action: STATE_SET "pulse" 0.0;
+              target: "progress";
+              transition: LINEAR 0.5;
+              after: "start_pulse";
+           }
+           program { name: "stop_pulse";
+              signal: "elm,state,pulse,stop";
+              source: "elm";
+              action: STATE_SET "default" 0.0;
+              target: "progress";
+           }
+        }
+      }
+   }
+
+   group { name: "elm/thumb/base/noframe";
+      images {
+        image: "busy-1.png" COMP;
+        image: "busy-2.png" COMP;
+        image: "busy-3.png" COMP;
+        image: "busy-4.png" COMP;
+        image: "busy-5.png" COMP;
+        image: "busy-6.png" COMP;
+        image: "busy-7.png" COMP;
+        image: "busy-8.png" COMP;
+        image: "busy-9.png" COMP;
+      }
+      parts {
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+           }
+        }
+        part { name: "progress";
+           mouse_events: 0;
+           description { state:        "default" 0.0;
+              min: 32 32;
+              max: 32 32;
+              visible: 0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+           }
+           description { state:        "pulse" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              image {
+                 normal: "busy-9.png";
+                 tween:  "busy-1.png";
+                 tween:  "busy-2.png";
+                 tween:  "busy-3.png";
+                 tween:  "busy-4.png";
+                 tween:  "busy-5.png";
+                 tween:  "busy-6.png";
+                 tween:  "busy-7.png";
+                 tween:  "busy-8.png";
+                 border: 7 7 7 7;
+              }
+           }
+        }
+        programs {
+           program { name: "start_pulse";
+              signal: "elm,state,pulse,start";
+              source: "elm";
+              action: STATE_SET "pulse" 0.0;
+              target: "progress";
+              transition: LINEAR 0.5;
+              after: "start_pulse";
+           }
+           program { name: "stop_pulse";
+              signal: "elm,state,pulse,stop";
+              source: "elm";
+              action: STATE_SET "default" 0.0;
+              target: "progress";
+           }
+        }
+      }
+   }
+
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/icon/home/default"; alias: "elm/icon/toolbar/home/default"; min: 32 32;
+      images.image: "icon_home.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_home.png"; } } } }
+   group { name: "elm/icon/close/default"; alias: "elm/icon/toolbar/close/default"; min: 32 32;
+      images.image: "icon_close.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_close.png"; } } } }
+   group { name: "elm/icon/apps/default"; alias: "elm/icon/toolbar/apps/default"; min: 32 32;
+      images.image: "icon_apps.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_apps.png"; } } } }
+   group { name: "elm/icon/arrow_up/default"; alias: "elm/icon/toolbar/arrow_up/default"; min: 32 32;
+      images.image: "icon_arrow_up.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_up.png"; } } } }
+   group { name: "elm/icon/arrow_down/default";
+           alias: "elm/icon/toolbar/arrow_down/default";
+           alias: "elm/icon/toolbar/more_menu/default"; min: 32 32;
+      images.image: "icon_arrow_down.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_down.png"; } } } }
+   group { name: "elm/icon/arrow_left/default"; alias: "elm/icon/toolbar/arrow_left/default"; min: 32 32;
+      images.image: "icon_arrow_left.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_left.png"; } } } }
+   group { name: "elm/icon/arrow_right/default"; alias: "elm/icon/toolbar/arrow_right/default"; min: 32 32;
+      images.image: "icon_arrow_right.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_right.png"; } } } }
+   group { name: "elm/icon/chat/default"; alias: "elm/icon/toolbar/chat/default"; min: 32 32;
+      images.image: "icon_chat.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_chat.png"; } } } }
+   group { name: "elm/icon/clock/default"; alias: "elm/icon/toolbar/clock/default"; min: 32 32;
+      images.image: "icon_clock.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_clock.png"; } } } }
+   group { name: "elm/icon/delete/default"; alias: "elm/icon/toolbar/delete/default"; min: 32 32;
+      images.image: "icon_delete.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_delete.png"; } } } }
+   group { name: "elm/icon/edit/default"; alias: "elm/icon/toolbar/edit/default"; min: 32 32;
+      images.image: "icon_edit.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_edit.png"; } } } }
+   group { name: "elm/icon/refresh/default"; alias: "elm/icon/toolbar/refresh/default"; min: 32 32;
+      images.image: "icon_refresh.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_refresh.png"; } } } }
+   group { name: "elm/icon/folder/default"; alias: "elm/icon/toolbar/folder/default"; min: 32 32;
+      images.image: "icon_folder.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_folder.png"; } } } }
+   group { name: "elm/icon/file/default"; alias: "elm/icon/toolbar/file/default"; min: 32 32;
+      images.image: "icon_file.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_file.png"; } } } }
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/icon/menu/home/default"; min: 24 24; max: 24 24;
+      images.image: "icon_home.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_home.png"; } } } }
+   group { name: "elm/icon/menu/close/default"; min: 24 24; max: 24 24;
+      images.image: "icon_close.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_close.png"; } } } }
+   group { name: "elm/icon/menu/apps/default"; min: 24 24; max: 24 24;
+      images.image: "icon_apps.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_apps.png"; } } } }
+   group { name: "elm/icon/menu/arrow_up/default"; min: 24 24; max: 24 24;
+      images.image: "icon_arrow_up.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_up.png"; } } } }
+   group { name: "elm/icon/menu/arrow_down/default"; min: 24 24; max: 24 24;
+      images.image: "icon_arrow_down.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_down.png"; } } } }
+   group { name: "elm/icon/menu/arrow_left/default"; min: 24 24; max: 24 24;
+      images.image: "icon_arrow_left.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_left.png"; } } } }
+   group { name: "elm/icon/menu/arrow_right/default"; min: 24 24; max: 24 24;
+      images.image: "icon_arrow_right.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_arrow_right.png"; } } } }
+   group { name: "elm/icon/menu/chat/default"; min: 24 24; max: 24 24;
+      images.image: "icon_chat.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_chat.png"; } } } }
+   group { name: "elm/icon/menu/clock/default"; min: 24 24; max: 24 24;
+      images.image: "icon_clock.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_clock.png"; } } } }
+   group { name: "elm/icon/menu/delete/default"; min: 24 24; max: 24 24;
+      images.image: "icon_delete.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_delete.png"; } } } }
+   group { name: "elm/icon/menu/edit/default"; min: 24 24; max: 24 24;
+      images.image: "icon_edit.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_edit.png"; } } } }
+   group { name: "elm/icon/menu/refresh/default"; min: 24 24; max: 24 24;
+      images.image: "icon_refresh.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_refresh.png"; } } } }
+   group { name: "elm/icon/menu/folder/default"; min: 24 24; max: 24 24;
+      images.image: "icon_folder.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_folder.png"; } } } }
+   group { name: "elm/icon/menu/file/default"; min: 24 24; max: 24 24;
+      images.image: "icon_file.png" COMP; parts { part { name: "base";
+        description { state: "default" 0.0; aspect: 1.0 1.0; aspect_preference: BOTH;
+           image.normal: "icon_file.png"; } } } }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/toolbar/base/default";
+      images {
+         image: "bt_dis_base.png" COMP;
+         image: "bt_dis_hilight.png" COMP;
+         image: "bt_dis_shine.png" COMP;
+         image: "icon_left_arrow.png" COMP;
+         image: "icon_right_arrow.png" COMP;
+      }
+      parts {
+         part { name: "base";
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 2 2;
+               }
+               rel2.offset: -3 -3;
+               image {
+                  normal: "bt_dis_base.png";
+                  border: 4 4 4 4;
+               }
+               image.middle: SOLID;
+            }
+         }
+         part { name: "clipper";
+            type: RECT;
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to: "base";
+                  offset: 2 2;
+               }
+               rel2 {
+                  to: "base";
+                  offset: -3 -3;
+               }
+            }
+         }
+         part { name: "elm.swallow.content";
+            clip_to: "clipper";
+            type: SWALLOW;
+            description {
+               state: "default" 0.0;
+               rel1.to: "clipper";
+               rel2.to: "clipper";
+            }
+         }
+         part { name: "over2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               image {
+                  normal: "bt_dis_shine.png";
+                  border: 4 4 4 4;
+               }
+            }
+         }
+         part { name: "over1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               rel2.relative: 1.0 0.5;
+               image {
+                  normal: "bt_dis_hilight.png";
+                  border: 4 4 4 0;
+               }
+               color: 255 255 255 128;
+            }
+         }
+         part { name: "left_arrow";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               image.normal: "icon_left_arrow.png";
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               align: 0.0 0.5;
+               min: 32 32;
+               max: 32 32;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+            }
+         }
+         part { name: "right_arrow";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               image.normal: "icon_right_arrow.png";
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               align: 1.0 0.5;
+               min: 32 32;
+               max: 32 32;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+            }
+         }
+         part { name: "event";
+            type: RECT;
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+      }
+      programs {
+         program { name: "sb_hbar_show";
+            signal: "elm,action,show,hbar";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            transition: LINEAR 0.5;
+            target: "left_arrow";
+            target: "right_arrow";
+         }
+         program { name: "sb_hbar_hide";
+            signal: "elm,action,hide,hbar";
+            source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "left_arrow";
+            target: "right_arrow";
+            transition: LINEAR 0.5;
+         }
+      }
+   }
+
+   group { name: "elm/toolbar/item/default";
+       images {
+           image: "toolbar_sel.png" COMP;
+       }
+       data.item: "transition_animation_on" "1";
+       parts {
+           part { name: "label2";
+               type: TEXT;
+               mouse_events:  0;
+               scale: 1;
+               clip_to: "elm.text.clipper";
+               description { state: "default" 0.0;
+                   align: 0.5 1.0;
+                   fixed: 0 1;
+                   rel1.to: "elm.text";
+                   rel2.to: "elm.text";
+                   color: 0 0 0 255;
+                   text {
+                       font: "Sans";
+                       text_source: "elm.text";
+                       size: 10;
+                       min: 1 1;
+                       align: 0.5 0.5;
+                       text_class: "toolbar_item";
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+               description { state: "disabled_visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+           }
+           part { name: "label2_new";
+               type: TEXT;
+               mouse_events:  0;
+               scale: 1;
+               clip_to: "elm.text_new.clipper";
+               description { state: "default" 0.0;
+                   align: 0.5 1.0;
+                   fixed: 0 1;
+                   rel1.to: "elm.text_new";
+                   rel2.to: "elm.text_new";
+                   color: 0 0 0 255;
+                   text {
+                       font: "Sans";
+                       text_source: "elm.text_new";
+                       size: 10;
+                       min: 1 1;
+                       align: 0.5 0.5;
+                       text_class: "toolbar_item";
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+               description { state: "disabled_visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+           }
+           part { name: "bg";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   image {
+                       normal: "toolbar_sel.png";
+                       border: 3 3 0 0;
+                   }
+                   image.middle: SOLID;
+                   fill.smooth: 0;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "elm.swallow.icon";
+               type: SWALLOW;
+               clip_to: "elm.icon.clipper";
+               description { state: "default" 0.0;
+                   align: 0.5 0.5;
+                   fixed: 0 0;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: 2 2;
+                   }
+                   rel2 {
+                       to_y: "elm.text";
+                       relative: 1.0 0.0;
+                       offset: -3 -1;
+                   }
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "elm.swallow.icon_new";
+               type: SWALLOW;
+               clip_to: "elm.icon_new.clipper";
+               description { state: "default" 0.0;
+                   align: 0.5 0.5;
+                   fixed: 0 0;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: 2 2;
+                   }
+                   rel2 {
+                       to_y: "elm.text_new";
+                       relative: 1.0 0.0;
+                       offset: -3 -1;
+                   }
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "elm.text";
+               type: TEXT;
+               effect: SOFT_SHADOW;
+               mouse_events:  0;
+               scale: 1;
+               clip_to: "elm.text.clipper";
+               description { state: "default" 0.0;
+                   align: 0.5 1.0;
+                   fixed: 0 1;
+                   rel1 {
+                       relative: 0.0 1.0;
+                       offset:   0 -1;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset:   -1 -1;
+                   }
+                   visible: 0;
+                   color: 224 224 224 255;
+                   color3: 0 0 0 32;
+                   text {
+                       font: "Sans:style=Bold";
+                       size: 10;
+                       min: 1 1;
+                       align: 0.5 0.5;
+                       text_class: "toolbar_item";
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+               description { state: "disabled_visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+           }
+           part { name: "elm.text_new";
+               type: TEXT;
+               effect: SOFT_SHADOW;
+               mouse_events:  0;
+               clip_to: "elm.text_new.clipper";
+               scale: 1;
+               description { state: "default" 0.0;
+                   align: 0.5 1.0;
+                   fixed: 0 1;
+                   rel1 {
+                       relative: 0.0 1.0;
+                       offset:   0 -1;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset:   -1 -1;
+                   }
+                   visible: 0;
+                   color: 224 224 224 255;
+                   color3: 0 0 0 32;
+                   text {
+                       font: "Sans:style=Bold";
+                       size: 10;
+                       min: 1 1;
+                       align: 0.5 0.5;
+                       text_class: "toolbar_item";
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+               description { state: "disabled_visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+                   visible: 1;
+                   text.min: 1 1;
+               }
+           }
+           part { name: "elm.text.clipper";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 255 255 255 255;
+               }
+               description { state: "animation" 0.0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "elm.text_new.clipper";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+               }
+               description { state: "animation" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "elm.icon.clipper";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 255 255 255 255;
+               }
+               description { state: "animation" 0.0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "elm.icon_new.clipper";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+               }
+               description { state: "animation" 0.0;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "event";
+               type: RECT;
+               mouse_events: 1;
+               ignore_flags: ON_HOLD;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+           }
+       }
+       programs {
+           program { name: "go_active";
+               signal:  "elm,state,selected";
+               source:  "elm";
+               action:  STATE_SET "selected" 0.0;
+               target:  "bg";
+               target:  "elm.text";
+               target:  "label2";
+               target:  "elm.text_new";
+               target:  "label2_new";
+               transition: LINEAR 0.2;
+           }
+           program { name: "go_passive";
+               signal:  "elm,state,unselected";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "bg";
+               target:  "elm.text";
+               target:  "label2";
+               target:  "elm.text_new";
+               target:  "label2_new";
+               transition: LINEAR 0.1;
+           }
+           program { name: "go";
+               signal:  "mouse,up,1";
+               source:  "event";
+               action:  SIGNAL_EMIT "elm,action,click" "elm";
+           }
+           program { name: "mouse,in";
+              signal:  "mouse,in";
+              source:  "event";
+              action:  SIGNAL_EMIT "elm,mouse,in" "elm";
+           }
+           program { name: "mouse,out";
+              signal:  "mouse,out";
+              source:  "event";
+              action:  SIGNAL_EMIT "elm,mouse,out" "elm";
+           }
+           program { name: "disable";
+               signal: "elm,state,disabled";
+               source: "elm";
+               action: STATE_SET "disabled" 0.0;
+               target: "label2";
+               target: "label2_new";
+               target: "bg";
+               after: "disable_text";
+           }
+           program { name: "disable_text";
+               script {
+                   new st[31];
+                   new Float:vl;
+                   get_state(PART:"elm.text", st, 30, vl);
+                   if (!strcmp(st, "visible"))
+                   {
+                      set_state(PART:"elm.text", "disabled_visible", 0.0);
+                      set_state(PART:"elm.text_new", "disabled_visible", 0.0);
+                   }
+                   else
+                   {
+                      set_state(PART:"elm.text", "disabled", 0.0);
+                      set_state(PART:"elm.text_new", "disabled", 0.0);
+                   }
+               }
+           }
+           program { name: "enable";
+               signal: "elm,state,enabled";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "label2";
+               target: "label2_new";
+               target: "bg";
+               after: "enable_text";
+           }
+           program { name: "enable_text";
+               script {
+                   new st[31];
+                   new Float:vl;
+                   get_state(PART:"elm.text", st, 30, vl);
+                   if (!strcmp(st, "disabled_visible"))
+                   {
+                      set_state(PART:"elm.text", "visible", 0.0);
+                      set_state(PART:"elm.text_new", "visible", 0.0);
+                   }
+                   else
+                   {
+                      set_state(PART:"elm.text", "default", 0.0);
+                      set_state(PART:"elm.text_new", "default", 0.0);
+                   }
+               }
+           }
+           program { name: "label_set,animation,forward";
+              signal: "elm,state,label_set,forward";
+              source: "elm";
+              after: "label_set,animation";
+           }
+           program { name: "label_set,animation,backward";
+              signal: "elm,state,label_set,backward";
+              source: "elm";
+              after: "label_set,animation";
+           }
+           program { name: "label_set,animation";
+              signal: "elm,state,label_set";
+              source: "elm";
+              action: STATE_SET "animation" 0.0;
+              target: "elm.text.clipper";
+              target: "elm.text_new.clipper";
+              transition: LINEAR 0.2;
+              after: "label_set,animation,done";
+           }
+           program { name: "label_set,animation,done";
+              action: SIGNAL_EMIT "elm,state,label_set,done" "elm";
+           }
+           program { name: "label,reset";
+              signal: "elm,state,label,reset";
+              source: "elm";
+              action: STATE_SET "default" 0.0;
+              target: "elm.text.clipper";
+              target: "elm.text_new.clipper";
+           }
+           program { name: "icon_set,animation,forward";
+              signal: "elm,state,icon_set,forward";
+              source: "elm";
+              after: "icon_set,animation";
+           }
+           program { name: "icon_set,animation,backward";
+              signal: "elm,state,icon_set,backward";
+              source: "elm";
+              after: "icon_set,animation";
+           }
+           program { name: "icon_set,animation";
+              signal: "elm,state,icon_set";
+              source: "elm";
+              action: STATE_SET "animation" 0.0;
+              target: "elm.icon.clipper";
+              target: "elm.icon_new.clipper";
+              transition: LINEAR 0.2;
+              after: "icon_set,animation,done";
+           }
+           program { name: "icon_set,animation,done";
+              action: SIGNAL_EMIT "elm,state,icon_set,done" "elm";
+           }
+           program { name: "icon,reset";
+              signal: "elm,state,icon,reset";
+              source: "elm";
+              action: STATE_SET "default" 0.0;
+              target: "elm.icon.clipper";
+              target: "elm.icon_new.clipper";
+           }
+       }
+   }
+
+   group { name: "elm/toolbar/separator/default";
+      images {
+         image: "toolbar_separator_v.png" COMP;
+      }
+      parts {
+         part { name: "separator"; // separator group
+            description { state: "default" 0.0;
+               min: 2 2;
+               max: 2 9999;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+              image {
+                 normal: "toolbar_separator_v.png";
+              }
+              fill {
+                 smooth: 0;
+              }
+           }
+        }
+      }
+   }
+
+   ///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/notify/block_events/default";
+       parts {
+           part { name: "block_events";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 0 0 0 64;
+                   visible: 1;
+               }
+           }
+       }
+          programs {
+                  program {
+                               name: "block_clicked";
+                               signal: "mouse,clicked,1";
+                               source: "block_events";
+                               action: SIGNAL_EMIT "elm,action,clicked" "elm";
+                  }
+          }
+   }
+   group { name: "elm/notify/top/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: 0.0 -1.0;
+                   rel2.relative: 1.0 0.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+                signal: "show";
+                action: STATE_SET "default" 0.0;
+                target: "base";
+                after: "show_3";
+           }
+           program { name: "show_3";
+                signal: "show";
+                action: STATE_SET "visible" 0.0;
+                target: "base";
+                transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/center/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "bt_dis_base.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+                signal: "show";
+                action: STATE_SET "default" 0.0;
+                target: "base";
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/bottom/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: 0.0 1.0;
+                   rel2.relative: 1.0 2.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+                signal: "show";
+                action: STATE_SET "default" 0.0;
+                target: "base";
+                after: "show_3";
+           }
+           program { name: "show_3";
+                signal: "show";
+                action: STATE_SET "visible" 0.0;
+                target: "base";
+                transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/left/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: -1.0 0.0;
+                   rel2.relative: 0.0 1.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+               signal: "show";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+               after: "show_3";
+           }
+           program { name: "show_3";
+               signal: "show";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+               transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/right/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+                description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: 1.0 0.0;
+                   rel2.relative: 2.0 1.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+               signal: "show";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+               after: "show_3";
+           }
+           program { name: "show_3";
+               signal: "show";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+               transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/top_left/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+                description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: 0.0 -1.0;
+                   rel2.relative: 1.0 0.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+               signal: "show";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+               after: "show_3";
+           }
+           program { name: "show_3";
+               signal: "show";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+               transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/top_right/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: 0.0 -1.0;
+                   rel2.relative: 1.0 0.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+               signal: "show";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+               after: "show_3";
+           }
+           program { name: "show_3";
+               signal: "show";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+               transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/bottom_left/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: 0.0 1.0;
+                   rel2.relative: 1.0 2.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+               signal: "show";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+               after: "show_3";
+           }
+           program { name: "show_3";
+               signal: "show";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+               transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+   group { name: "elm/notify/bottom_right/default";
+       //this group is a design similar to the inwin group
+       images {
+           image: "shad_circ.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+       }
+       parts {
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               repeat_events: 1;
+              description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   rel1.offset: 10 10;
+                   rel2.offset: -10 -10;
+                   rel1.relative: 0.0 1.0;
+                   rel2.relative: 1.0 2.0;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 64;
+                   rel1.relative: 0.0 0.0;
+                   rel2.relative: 1.0 1.0;
+               }
+           }
+           part { name: "shad";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   image.normal: "shad_circ.png";
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -64 -64;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 63 63;
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "pop";
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.swallow.content";
+                   rel1.offset: -5 -5;
+                   rel2.to: "elm.swallow.content";
+                   rel2.offset: 4 4;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "popover";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "pop";
+                   rel2.to: "pop";
+                   rel2.relative: 1.0 0.5;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.to: "base";
+                   rel2.to: "base";
+               }
+           }
+       }
+       programs {
+           program { name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+           }
+           program { name: "show_2";
+               signal: "show";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+               after: "show_3";
+           }
+           program { name: "show_3";
+               signal: "show";
+               action: STATE_SET "visible" 0.0;
+               target: "base";
+               transition: LINEAR 0.5;
+           }
+           program { name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "base";
+           }
+       }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/slideshow/base/default";
+      data {
+         item: transitions "fade black_fade horizontal vertical square";
+         item: layouts "fullscreen not_fullscreen";
+      }
+      parts {
+         part { name: "whole";
+               type: RECT;
+            description {
+               state: "default" 0.0;
+               visible: 1;
+               color: 20 20 20 255;
+            }
+         }
+         part { name: "image_1_whole";
+            description {
+               state: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "fade_prev_next" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 0;
+            }
+            description {
+               state: "black_fade_prev_next_init" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "black_fade_prev_next" 0.0;
+               inherit: "default" 0.0;
+               color: 0 0 0 255;
+            }
+            description {
+               state: "horizontal_next_init" 0.0;
+               inherit: "default" 0.0;
+            }
+            description {
+               state: "horizontal_next" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: -1.0 0.0;
+               rel2.relative: 0.0 1.0;
+            }
+            description {
+               state: "horizontal_prev_init" 0.0;
+               inherit: "default" 0.0;
+            }
+            description {
+               state: "horizontal_prev" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 1.0 0.0;
+               rel2.relative: 2.0 1.0;
+            }
+            description {
+               state: "vertical_next_init" 0.0;
+               inherit: "default" 0.0;
+            }
+            description {
+               state: "vertical_next" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 -1.0;
+               rel2.relative: 1.0 0.0;
+            }
+            description {
+               state: "vertical_prev_init" 0.0;
+               inherit: "default" 0.0;
+            }
+            description {
+               state: "vertical_prev" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 1.0;
+               rel2.relative: 1.0 2.0;
+            }
+            description {
+               state: "square_prev_next" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 0;
+            }
+         }
+         part { name: "image_2_whole";
+            description {
+               state: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 0;
+            }
+            description {
+               state: "fade_prev_next" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "black_fade_prev_next_init" 0.0;
+               inherit: "default" 0.0;
+               color: 0 0 0 0;
+            }
+            description {
+               state: "black_fade_prev_next" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "horizontal_next_init" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 1.0 0.0;
+               rel2.relative: 2.0 1.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "horizontal_next" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "horizontal_prev_init" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: -1.0 0.0;
+               rel2.relative: 0.0 1.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "horizontal_prev" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "vertical_next_init" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 1.0;
+               rel2.relative: 1.0 2.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "vertical_next" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "vertical_prev_init" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 -1.0;
+               rel2.relative: 1.0 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "vertical_prev" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "square_prev_next_init" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.5 0.5;
+               rel2.relative: 0.5 0.5;
+               color: 255 255 255 255;
+            }
+            description {
+               state: "square_prev_next" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 1.0 1.0;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "elm.swallow.1";
+            type: SWALLOW;
+            clip_to: "image_1_whole";
+            description {
+               state: "default" 0.0;
+               rel1.to: "image_1_whole";
+               rel2.to: "image_1_whole";
+               color: 255 255 255 255;
+            }
+            description {
+               state: "not_fullscreen" 0.0;
+               rel1.relative: 0.1 0.1;
+               rel1.to: "image_1_whole";
+               rel2.relative: 0.9 0.9;
+               rel2.to: "image_1_whole";
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "elm.swallow.2";
+            type: SWALLOW;
+            clip_to: "image_2_whole";
+            description {
+               state: "default" 0.0;
+               color: 255 255 255 255;
+               rel1.to: "image_2_whole";
+               rel2.to: "image_2_whole";
+            }
+            description {
+               state: "not_fullscreen" 0.0;
+               color: 255 255 255 255;
+               rel1.relative: 0.1 0.1;
+               rel1.to: "image_2_whole";
+               rel2.relative: 0.9 0.9;
+               rel2.to: "image_2_whole";
+            }
+         }
+         part { name: "events_catcher";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               visible: 1;
+               color: 0 0 0 0;
+            }
+         }
+      }
+      programs {
+       //Substyle
+       program { name: "layout_fullscreen";
+            signal: "layout,fullscreen";
+            source: "slideshow";
+            action: STATE_SET "default" 0.0;
+            target: "elm.swallow.1";
+            target: "elm.swallow.2";
+            transition: SINUSOIDAL 1.0;
+        }
+        program { name: "layout_not_fullscreen";
+            signal: "layout,not_fullscreen";
+            source: "slideshow";
+            action: STATE_SET "not_fullscreen" 0.0;
+            target: "elm.swallow.1";
+            target: "elm.swallow.2";
+            transition: SINUSOIDAL 1.0;
+         } 
+        //
+         program { name: "fade_next";
+            signal: "fade,next";
+            source: "slideshow";
+            action: STATE_SET "default" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "fade_next_2";
+         }
+         program { name: "fade_next_2";
+            action: STATE_SET "fade_prev_next" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            transition: SINUSOIDAL 1.5;
+            after: "end";
+         }
+         program { name: "fade_previous";
+            signal: "fade,previous";
+            source: "slideshow";
+            action: STATE_SET "default" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "fade_previous_2";
+         }
+         program { name: "fade_previous_2";
+            action: STATE_SET "fade_prev_next" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            transition: SINUSOIDAL 1.5;
+            after: "end";
+         }
+         program { name: "black_fade_next";
+            signal: "black_fade,next";
+            source: "slideshow";
+            action: STATE_SET "black_fade_prev_next_init" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "black_fade_next_2";
+         }
+         program { name: "black_fade_next_2";
+            action: STATE_SET "black_fade_prev_next" 0.0;
+            target: "image_1_whole";
+            transition: SINUSOIDAL 0.75;
+            after: "black_fade_next_3";
+         }
+         program { name: "black_fade_next_3";
+            action: STATE_SET "black_fade_prev_next" 0.0;
+            target: "image_2_whole";
+            transition: SINUSOIDAL 0.75;
+            after: "end";
+         }
+         program { name: "black_fade_previous";
+            signal: "black_fade,previous";
+            source: "slideshow";
+            action: STATE_SET "black_fade_prev_next_init" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "black_fade_previous_2";
+         }
+         program { name: "black_fade_previous_2";
+            action: STATE_SET "black_fade_prev_next" 0.0;
+            target: "image_1_whole";
+            transition: SINUSOIDAL 0.75;
+            after: "black_fade_previous_3";
+         }
+         program { name: "black_fade_previous_3";
+            action: STATE_SET "black_fade_prev_next" 0.0;
+            target: "image_2_whole";
+            transition: SINUSOIDAL 0.75;
+            after: "end";
+         }
+         program { name: "horizontal_next";
+            signal: "horizontal,next";
+            source: "slideshow";
+            action: STATE_SET "horizontal_next_init" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "horizontal_next_2";
+         }
+         program { name: "horizontal_next_2";
+            action: STATE_SET "horizontal_next" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            transition: SINUSOIDAL 1.5;
+            after: "end";
+         }
+         program { name: "horizontal_previous";
+            signal: "horizontal,previous";
+            source: "slideshow";
+            action: STATE_SET "horizontal_prev_init" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "horizontal_previous_2";
+         }
+         program { name: "horizontal_previous_2";
+            action: STATE_SET "horizontal_prev" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            transition: SINUSOIDAL 1.5;
+            after: "end";
+         }
+         program { name: "vertical_next";
+            signal: "vertical,next";
+            source: "slideshow";
+            action: STATE_SET "vertical_next_init" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "vertical_next_2";
+         }
+         program { name: "vertical_next_2";
+            action: STATE_SET "vertical_next" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            transition: SINUSOIDAL 1.5;
+            after: "end";
+         }
+         program { name: "vertical_previous";
+            signal: "vertical,previous";
+            source: "slideshow";
+            action: STATE_SET "vertical_prev_init" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            after: "vertical_previous_2";
+         }
+         program { name: "vertical_previous_2";
+            action: STATE_SET "vertical_prev" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+            transition: SINUSOIDAL 1.5;
+            after: "end";
+         }
+         program { name: "square_next";
+            signal: "square,next";
+            source: "slideshow";
+            action: STATE_SET "square_prev_next_init" 0.0;
+            target: "image_2_whole";
+            after: "square_next_2";
+         }
+         program { name: "square_next_2";
+            action: STATE_SET "square_prev_next" 0.0;
+            target: "image_2_whole";
+            target: "image_1_whole";
+            transition: SINUSOIDAL 1.5;
+            after: "end";
+         }
+         program { name: "square_previous";
+            signal: "square,previous";
+            source: "slideshow";
+            action: STATE_SET "square_prev_next_init" 0.0;
+            target: "image_2_whole";
+            after: "square_next_2";
+         }
+         program { name: "end";
+            action: SIGNAL_EMIT "end" "slideshow";
+         }
+         program { name: "end_signal";
+           signal: "anim,end";
+           source: "slideshow";
+            action: STATE_SET "default" 0.0;
+            target: "image_1_whole";
+            target: "image_2_whole";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/win/inwin/default";
+      images {
+        image: "shad_circ.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+      }
+      parts {
+        part { name: "base";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 1.0;
+              color: 0 0 0 64;
+           }
+        }
+         part { name: "shad";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "shad_circ.png";
+              rel1.to: "elm.swallow.content";
+              rel1.offset: -64 -64;
+              rel2.to: "elm.swallow.content";
+              rel2.offset: 63 63;
+               fill.smooth: 0;
+           }
+        }
+        part { name: "pop";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.content";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.content";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+        }
+         part { name: "popover";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "pop";
+              rel2.to: "pop";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "elm.swallow.content";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+               rel1.relative: 0.1 0.1;
+               rel2.relative: 0.9 0.9;
+           }
+        }
+      }
+      programs {
+        program { name: "show";
+            signal: "elm,action,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+        program { name: "hide";
+            signal: "elm,action,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+      }
+   }
+
+   group { name: "elm/win/inwin/minimal";
+      images {
+        image: "shad_circ.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+      }
+      parts {
+        part { name: "base";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 1.0;
+              color: 0 0 0 64;
+           }
+        }
+         part { name: "shad";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "shad_circ.png";
+              rel1.to: "elm.swallow.content";
+              rel1.offset: -64 -64;
+              rel2.to: "elm.swallow.content";
+              rel2.offset: 63 63;
+               fill.smooth: 0;
+           }
+        }
+        part { name: "pop";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.content";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.content";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+        }
+         part { name: "popover";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "pop";
+              rel2.to: "pop";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "elm.swallow.content";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.relative: 0.5 0.5;
+               rel2.relative: 0.5 0.5;
+           }
+        }
+      }
+      programs {
+        program { name: "show";
+            signal: "elm,action,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+        program { name: "hide";
+            signal: "elm,action,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+      }
+   }
+
+   group { name: "elm/win/inwin/minimal_vertical";
+      images {
+        image: "shad_circ.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+      }
+      parts {
+        part { name: "base";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 1.0;
+              color: 0 0 0 64;
+           }
+        }
+         part { name: "shad";
+           mouse_events:  0;
+           description { state: "default" 0.0;
+              image.normal: "shad_circ.png";
+              rel1.to: "elm.swallow.content";
+              rel1.offset: -64 -64;
+              rel2.to: "elm.swallow.content";
+              rel2.offset: 63 63;
+               fill.smooth: 0;
+           }
+        }
+        part { name: "pop";
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "elm.swallow.content";
+               rel1.offset: -5 -5;
+              rel2.to: "elm.swallow.content";
+               rel2.offset: 4 4;
+               image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+               image.middle: SOLID;
+           }
+        }
+         part { name: "popover";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "pop";
+              rel2.to: "pop";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "elm.swallow.content";
+            type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.relative: 0.1 0.5;
+               rel2.relative: 0.9 0.5;
+           }
+        }
+      }
+      programs {
+        program { name: "show";
+            signal: "elm,action,show";
+           source: "elm";
+           action: STATE_SET "visible" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+        program { name: "hide";
+            signal: "elm,action,hide";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+//         transition: DECELERATE 0.5;
+           target: "base";
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/list/item/default";
+      data.item: "stacking" "above";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+   group { name: "elm/list/item_odd/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part {
+            name:          "elm.swallow.icon";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part {
+            name:          "elm.swallow.end";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part {
+            name:           "elm.text";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min:      16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+   group { name: "elm/list/item_compress/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               align: 0.0 0.0;
+               min: 0 10;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name:          "elm.swallow.icon";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name:          "elm.swallow.end";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    1.0 0.5;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part {
+            name:           "elm.text";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description { state: "default" 0.0;
+//               min:      16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+   group { name: "elm/list/item_compress_odd/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name:          "elm.swallow.icon";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name:          "elm.swallow.end";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    1.0 0.5;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part {
+            name:           "elm.text";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min:      16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/list/h_item/default";
+      data.item: "stacking" "above";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1_h.png" COMP;
+         image: "ilist_item_shadow_h.png" COMP;
+      }
+      parts {
+         part {
+            name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 10 0;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 1.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: 0 -1;
+               }
+               image {
+                  normal: "ilist_item_shadow_h.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1_h.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -5 4;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 1.0;
+               rel1 {
+                  relative: 0.0 1.0;
+                  offset: 4 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -5 -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               fixed: 0 1;
+               rel1 {
+                  to_x: "elm.swallow.icon";
+                  relative: 0.0 1.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.end";
+                  relative: 1.0 0.0;
+                  offset: -5 -1;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name: "go_active";
+            signal: "elm,state,selected";
+            source: "elm";
+            action: STATE_SET "selected" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+         }
+         program {
+            name: "go_passive";
+            signal: "elm,state,unselected";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+   group { name: "elm/list/h_item_odd/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2_h.png" COMP;
+      }
+      parts {
+         part {
+            name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2_h.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part {
+            name: "elm.swallow.icon";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -5 4;
+               }
+            }
+         }
+         part {
+            name: "elm.swallow.end";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 1.0;
+               rel1 {
+                  relative: 0.0 1.0;
+                  offset: 4 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -5 -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               fixed: 1 1;
+               rel1 {
+                  to_x: "elm.swallow.icon";
+                  relative: 0.0 1.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.end";
+                  relative: 1.0 0.0;
+                  offset: -5 -1;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name: "go_active";
+            signal: "elm,state,selected";
+            source: "elm";
+            action: STATE_SET "selected" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+         }
+         program {
+            name: "go_passive";
+            signal: "elm,state,unselected";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+   group { name: "elm/list/h_item_compress/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1_h.png" COMP;
+         image: "ilist_item_shadow_h.png" COMP;
+      }
+      parts {
+         part {
+            name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               align: 0.0 0.0;
+               min: 10 0;
+               rel1 {
+                  to: "base";
+                  relative: 1.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: 0 -1;
+               }
+               image {
+                  normal: "ilist_item_shadow_h.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1_h.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -5 4;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 1.0;
+               rel1 {
+                  relative: 0.0 1.0;
+                  offset: 4 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -5 -5;
+               }
+            }
+         }
+         part {
+            name: "elm.text";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1 {
+                  to_x: "elm.swallow.icon";
+                  relative: 0.0 1.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.end";
+                  relative: 1.0 0.0;
+                  offset: -5 -1;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name: "go_active";
+            signal: "elm,state,selected";
+            source: "elm";
+            action: STATE_SET "selected" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+         }
+         program {
+            name: "go_passive";
+            signal: "elm,state,unselected";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+   group { name: "elm/list/h_item_compress_odd/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2_h.png" COMP;
+      }
+      parts {
+         part {
+            name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2_h.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -5 4;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 1.0;
+               rel1 {
+                  relative: 0.0 1.0;
+                  offset: 4 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -5 -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               fixed: 1 1;
+               rel1 {
+                  to_x: "elm.swallow.icon";
+                  relative: 0.0 1.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.end";
+                  relative: 1.0 0.0;
+                  offset: -5 -1;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+      }
+      programs {
+         program {
+            name: "go_active";
+            signal: "elm,state,selected";
+            source: "elm";
+            action: STATE_SET "selected" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+         }
+         program {
+            name: "go_passive";
+            signal: "elm,state,unselected";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "bg";
+            target: "fg1";
+            target: "fg2";
+            target: "elm.text";
+            transition: LINEAR 0.1;
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/slider/horizontal/default";
+           alias: "elm/slider/horizontal/disabled";
+      images {
+        image: "sl_bg.png" COMP;
+        image: "sl_bg_over.png" COMP;
+        image: "sl_bt_0.png" COMP;
+        image: "sl_bt_1.png" COMP;
+        image: "sl_bt_2.png" COMP;
+        image: "sl_bt_3.png" COMP;
+        image: "sl_bt2_0_0.png" COMP;
+        image: "sl_bt2_0_1.png" COMP;
+        image: "sl_bt2_0_2.png" COMP;
+        image: "sl_bt2_1.png" COMP;
+        image: "sl_bt2_2.png" COMP;
+         image: "sl_units.png" COMP;
+      }
+      script {
+         public value_hide = 0;
+         public set_value_show() {
+            set_int(value_hide, 0);
+         }
+         public set_value_hide() {
+            set_int(value_hide, 1);
+         }
+         public thumb_down() {
+            if (get_int(value_hide) == 1) {
+               set_state(PART:"elm.indicator", "default", 0.0);
+               set_state(PART:"button3", "default", 0.0);
+               set_state(PART:"button4", "default", 0.0);
+               set_state(PART:"button5", "default", 0.0);
+               set_state(PART:"button6", "default", 0.0);
+               set_state(PART:"button7", "default", 0.0);
+            } else {
+               set_state(PART:"elm.indicator", "visible", 0.0);
+               set_state(PART:"button3", "visible", 0.0);
+               set_state(PART:"button4", "visible", 0.0);
+               set_state(PART:"button5", "visible", 0.0);
+               set_state(PART:"button6", "visible", 0.0);
+               set_state(PART:"button7", "visible", 0.0);
+            }
+         }
+         public thumb_up() {
+            set_state(PART:"elm.indicator", "default", 0.0);
+            set_state(PART:"button3", "default", 0.0);
+            set_state(PART:"button4", "default", 0.0);
+            set_state(PART:"button5", "default", 0.0);
+            set_state(PART:"button6", "default", 0.0);
+            set_state(PART:"button7", "default", 0.0);
+         }
+      }
+      parts {
+         part { name: "base";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               max: 99999 6;
+               min: 0 6;
+               rel1 { to: "bg";
+                  offset: 1 0;
+               }
+               rel2 { to: "bg";
+                  offset: -2 -1;
+               }
+               image.normal: "sl_bg.png";
+               fill.smooth: 0;
+            }
+         }
+         part { name: "level";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "base";
+               rel2 {
+                  to_y: "base";
+                  to_x: "elm.dragable.slider";
+                  relative: 0.5 1.0;
+               }
+               color: 255 0 0 200;
+            }
+            description { state: "inverted" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 0 0 100;
+            }
+            description { state: "disabled_inverted" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+            }
+         }
+         part { name: "level2";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               visible: 0;
+               rel1 {
+                  to_y: "base";
+                  to_x: "elm.dragable.slider";
+                  relative: 0.5 0.0;
+               }
+               rel2.to: "base";
+               color: 255 0 0 200;
+            }
+            description { state: "inverted" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+            }
+            description { state: "disabled_inverted" 0.0;
+               inherit: "default" 0.0;
+               color: 255 0 0 100;
+               visible: 1;
+            }
+         }
+         part {
+            name: "base_over";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel1.offset: -1 -1;
+               rel2.to: "base";
+               rel2.offset: 0 0;
+               image {
+                  normal: "sl_bg_over.png";
+                  border: 3 3 3 3;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+           type: RECT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+               visible: 0;
+              rel1.to: "elm.swallow.bar";
+              rel2.to: "elm.swallow.bar";
+              color: 0 0 0 0;
+           }
+        }
+        part { name: "elm.swallow.bar";
+           type: SWALLOW;
+            scale: 1;
+           description { state: "default" 0.0;
+              min: 48 24;
+              max: 99999 24;
+              align: 1.0 0.5;
+              rel1 {
+                  to_x: "elm.text";
+                  relative: 1.0 0.0;
+                  offset: 8 0;
+               }
+              rel2 {
+                  to_x: "elm.units";
+                  relative: 0.0 1.0;
+                  offset: -10 -1;
+               }
+           }
+        }
+        part { name: "elm.swallow.icon";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              visible: 0;
+              align: 0.0 0.5;
+              rel1 {
+                  offset: 4 0;
+                  to_y: "elm.swallow.bar";
+               }
+              rel2 {
+                  offset: 3 -1;
+                  relative: 0.0 1.0;
+                  to_y: "elm.swallow.bar";
+               }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+              rel2.offset: 4 -1;
+           }
+        }
+         part { name: "elm.text";
+           type: TEXT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+               fixed: 1 1;
+               align: 0.0 0.5;
+              rel1.to_x: "elm.swallow.icon";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: -1 4;
+              rel2.to_x: "elm.swallow.icon";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -1 -5;
+              color: 0 0 0 255;
+              text {
+                 font: "Sans,Edje-Vera";
+                 size: 10;
+                 min: 0 0;
+                 align: 0.0 0.5;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+               rel1.offset: 0 4;
+               rel2.offset: 0 -5;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 255 128 128 128;
+              visible: 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+        part {
+            name: "elm.swallow.end";
+            type: SWALLOW;
+           description {
+               state: "default" 0.0;
+              visible: 0;
+              align: 1.0 0.5;
+              rel1 {
+                  offset: -4 0;
+                  relative: 1.0 0.0;
+                  to_y: "elm.swallow.bar";
+               }
+              rel2 {
+                  offset: -3 -1;
+                  to_y: "elm.swallow.bar";
+               }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+              rel2.offset: -4 -1;
+           }
+        }
+         part { name: "units";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               rel1 {
+                  to_x: "elm.units";
+                  offset: 0 5;
+               }
+               rel2 {
+                  to_x: "elm.units";
+                  offset: 5 -3;
+               }
+               image {
+                  normal: "sl_units.png";
+                  border: 0 5 3 8;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "elm.units";
+           type: TEXT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+               fixed: 1 1;
+              align: 1.0 0.5;
+              rel1.to_x: "elm.swallow.end";
+              rel1.relative: 0.0 0.0;
+               rel1.offset: 0 8;
+              rel2.to_x: "elm.swallow.end";
+              rel2.relative: 0.0 1.0;
+              rel2.offset: 0 -9;
+              color: 0 0 0 255;
+              text {
+                 font: "Sans,Edje-Vera";
+                 size: 10;
+                 min: 0 0;
+                 align: 0.0 0.5;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+               fixed: 1 1;
+              visible: 1;
+              text.min: 1 1;
+              rel1.offset: -5 0;
+              rel2.offset: -5 -1;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 255 128 128 128;
+              visible: 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+         part { name: "elm.dragable.slider";
+            type: RECT;
+            mouse_events: 0;
+            scale: 1;
+            dragable {
+               x: 1 1 0;
+               y: 0 0 0;
+               confine: "bg";
+            }
+            description { state: "default" 0.0;
+               min: 0 24;
+               max: 0 24;
+               fixed: 1 1;
+               rel1 {
+                  relative: 0.5 0.0;
+                  to_x: "bg";
+               }
+               rel2 {
+                  relative: 0.5 1.0;
+                  to_x: "bg";
+               }
+               color: 255 0 0 100;
+            }
+         }
+         part { name: "button_events";
+           type: RECT;
+           dragable {
+              events: "elm.dragable.slider";
+           }
+            mouse_events: 1;
+           description { state: "default" 0.0;
+               fixed: 1 1;
+               min: 16 16;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+              rel1.to_x: "elm.dragable.slider";
+              rel2.to_x: "elm.dragable.slider";
+              color: 0 0 0 0;
+           }
+        }
+         part { name: "button0";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               max: 17 999;
+               min: 17 24;
+               rel1.to: "elm.dragable.slider";
+               rel2.to: "elm.dragable.slider";
+               image {
+                  normal: "sl_bt_0.png";
+                  border: 5 5 5 10;
+               }
+               fill.smooth: 0;
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               image {
+                  normal: "sl_bt_3.png";
+                  border: 5 5 5 10;
+               }
+            }
+         }
+         part { name: "button1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button0";
+               rel2 {
+                  to: "button0";
+                  relative: 1.0 0.5;
+                  offset: -1 -5;
+               }
+               image {
+                  normal: "sl_bt_1.png";
+                  border: 5 5 5 0;
+               }
+            }
+         }
+         part { name: "button2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button0";
+               rel2.to: "button0";
+               image {
+                  normal: "sl_bt_2.png";
+                  border: 5 5 5 10;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "button3";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+              visible: 0;
+               min: 8 32;
+               align: 1.0 0.5;
+               rel1 {
+                  to_x: "elm.indicator";
+                  to_y: "button4";
+                  relative: 0.0 0.0;
+                  offset: -7 0;
+               }
+               rel2 {
+                  to: "button4";
+                  relative: 0.0 1.0;
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "sl_bt2_0_0.png";
+                  border: 6 0 6 12;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "button4";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               max: 15 999;
+               min: 15 32;
+               rel1 {
+                  to_x: "button0";
+                  to_y: "elm.indicator";
+                  offset: 0 0;
+               }
+               rel2.to: "button0";
+               image {
+                  normal: "sl_bt2_0_1.png";
+                  border: 0 0 6 12;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "button5";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+              visible: 0;
+               min: 8 32;
+               align: 0.0 0.5;
+               rel1 {
+                  to: "button4";
+                  relative: 1.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to_x: "elm.indicator";
+                  to_y: "button4";
+                  relative: 1.0 1.0;
+                  offset: 6 -1;
+               }
+               image {
+                  normal: "sl_bt2_0_2.png";
+                  border: 0 6 6 12;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "elm.indicator";
+           type: TEXT;
+           mouse_events: 0;
+            effect: SOFT_SHADOW;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+               fixed: 1 1;
+               align: 0.5 1.0;
+              rel1 {
+                  to: "button0";
+                  relative: 0.0 -0.25;
+                  offset: 0 0;
+               }
+              rel2 {
+                  to_x: "button0";
+                  relative: 1.0 -0.25;
+                  offset: -1 0;
+               }
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 0;
+                 align:    0.5 0.5;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+               rel1.offset: 0 -1;
+               rel2.offset: -1 -1;
+           }
+        }
+         part { name: "button6";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               rel1.to: "button3";
+               rel2 {
+                  to: "button5";
+                  relative: 1.0 0.3;
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "sl_bt2_1.png";
+                  border: 5 5 5 0;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "button7";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               rel1.to: "button3";
+               rel2.to: "button5";
+               image {
+                  normal: "sl_bt2_2.png";
+                  border: 5 5 5 0;
+                  middle: 0;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.text";
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.text";
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.swallow.icon";
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.icon";
+        }
+        program { name: "end_show";
+           signal: "elm,state,end,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.swallow.end";
+        }
+        program { name: "end_hide";
+           signal: "elm,state,end,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.end";
+        }
+        program { name: "units_show";
+           signal: "elm,state,units,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.units";
+           target: "units";
+        }
+        program { name: "units_hide";
+           signal: "elm,state,units,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.units";
+           target: "units";
+        }
+        program { name: "invert_on";
+           signal: "elm,state,inverted,on";
+           source: "elm";
+           action:  STATE_SET "inverted" 0.0;
+           target: "level";
+           target: "level2";
+        }
+        program { name: "invert_off";
+           signal: "elm,state,inverted,off";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "level";
+           target: "level2";
+        }
+        program { name: "set_val_show";
+           signal: "elm,state,val,show";
+           source: "elm";
+           script {
+               set_value_show();
+           }
+        }
+        program { name: "set_val_hide";
+           signal: "elm,state,val,hide";
+           source: "elm";
+           script {
+               set_value_hide();
+           }
+        }
+        program { name: "val_show";
+           signal: "mouse,down,*";
+           source: "elm.dragable.slider";
+           script {
+               thumb_down();
+           }
+
+        }
+        program { name: "val_hide";
+           signal: "mouse,up,*";
+           source: "elm.dragable.slider";
+           script {
+               thumb_up();
+           }
+        }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "button0";
+            target:  "disabler";
+            after: "disable_text";
+         }
+         program { name: "disable_text";
+            script {
+               new st[31];
+               new Float:vl;
+               get_state(PART:"elm.text", st, 30, vl);
+               if (!strcmp(st, "visible"))
+                  set_state(PART:"elm.text", "disabled_visible", 0.0);
+               else
+                  set_state(PART:"elm.text", "disabled", 0.0);
+
+               get_state(PART:"elm.units", st, 30, vl);
+               if (!strcmp(st, "visible")) 
+                  set_state(PART:"elm.units", "disabled_visible", 0.0);
+               else 
+                  set_state(PART:"elm.units", "disabled", 0.0);
+
+               get_state(PART:"level2", st, 30, vl);
+               if (!strcmp(st, "inverted")) 
+               {
+                  set_state(PART:"level", "disabled_inverted", 0.0);
+                  set_state(PART:"level2", "disabled_inverted", 0.0);
+               }
+               else 
+               {
+                  set_state(PART:"level", "disabled", 0.0);
+                  set_state(PART:"level2", "disabled", 0.0);
+               }
+            }
+         }
+         program { name: "enable";
+            signal: "elm,state,enabled";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "button0";
+            target: "disabler";
+            after: "enable_text";
+         }
+         program { name: "enable_text";
+            script {
+               new st[31];
+               new Float:vl;
+               get_state(PART:"elm.text", st, 30, vl);
+               if (!strcmp(st, "disabled_visible"))
+                  set_state(PART:"elm.text", "visible", 0.0);
+               else
+                  set_state(PART:"elm.text", "default", 0.0);
+
+               get_state(PART:"elm.units", st, 30, vl);
+               if (!strcmp(st, "disabled_visible"))
+                  set_state(PART:"elm.units", "visible", 0.0);
+               else
+                  set_state(PART:"elm.units", "default", 0.0);
+     
+               get_state(PART:"level2", st, 30, vl);
+               if (!strcmp(st, "disabled_inverted"))
+               {
+                  set_state(PART:"level", "inverted", 0.0);
+                  set_state(PART:"level2", "inverted", 0.0);
+               }
+               else
+               {
+                  set_state(PART:"level", "default", 0.0);
+                  set_state(PART:"level2", "default", 0.0);
+               }
+            }
+         }
+      }
+   }
+
+   group { name: "elm/slider/vertical/default";
+      images {
+        image: "slv_bg.png" COMP;
+        image: "slv_bg_over.png" COMP;
+
+        image: "sl_bt_0.png" COMP;
+        image: "sl_bt_1.png" COMP;
+        image: "sl_bt_2.png" COMP;
+        image: "sl_bt_3.png" COMP;
+        image: "sl_bt2_0_0.png" COMP;
+        image: "sl_bt2_0_1.png" COMP;
+        image: "sl_bt2_0_2.png" COMP;
+        image: "sl_bt2_1.png" COMP;
+        image: "sl_bt2_2.png" COMP;
+
+         image: "slv_units.png" COMP;
+      }
+      script {
+         public value_hide = 0;
+         public set_value_show() {
+            set_int(value_hide, 0);
+         }
+         public set_value_hide() {
+            set_int(value_hide, 1);
+         }
+         public thumb_down() {
+            if (get_int(value_hide) == 1) {
+               set_state(PART:"elm.indicator", "default", 0.0);
+               set_state(PART:"button3", "default", 0.0);
+               set_state(PART:"button4", "default", 0.0);
+               set_state(PART:"button5", "default", 0.0);
+               set_state(PART:"button6", "default", 0.0);
+               set_state(PART:"button7", "default", 0.0);
+            } else {
+               set_state(PART:"elm.indicator", "visible", 0.0);
+               set_state(PART:"button3", "visible", 0.0);
+               set_state(PART:"button4", "visible", 0.0);
+               set_state(PART:"button5", "visible", 0.0);
+               set_state(PART:"button6", "visible", 0.0);
+               set_state(PART:"button7", "visible", 0.0);
+            }
+         }
+         public thumb_up() {
+            set_state(PART:"elm.indicator", "default", 0.0);
+            set_state(PART:"button3", "default", 0.0);
+            set_state(PART:"button4", "default", 0.0);
+            set_state(PART:"button5", "default", 0.0);
+            set_state(PART:"button6", "default", 0.0);
+            set_state(PART:"button7", "default", 0.0);
+         }
+      }
+      parts {
+         part { name: "base";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               max: 6 99999;
+               min: 6 0;
+               rel1 { to: "bg";
+                  offset: 1 0;
+               }
+               rel2 { to: "bg";
+                  offset: -2 -1;
+               }
+               image.normal: "slv_bg.png";
+               fill.smooth: 0;
+            }
+         }
+         part { name: "level";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "base";
+               rel2 {
+                  to_x: "base";
+                  to_y: "elm.dragable.slider";
+                  relative: 1.0 0.5;
+               }
+               color: 255 0 0 200;
+            }
+            description { state: "inverted" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 0 0 100;
+            }
+            description { state: "disabled_inverted" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+            }
+         }
+         part { name: "level2";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               visible: 0;
+               rel1 {
+                  to_x: "base";
+                  to_y: "elm.dragable.slider";
+                  relative: 0.0 0.5;
+               }
+               rel2.to: "base";
+               color: 255 0 0 200;
+            }
+            description { state: "inverted" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 0 0 100;
+            }
+            description { state: "disabled_inverted" 0.0;
+               inherit: "default" 0.0;
+               color: 255 0 0 100;
+               visible: 1;
+            }
+         }
+         part {
+            name: "base_over";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel1.offset: -1 -1;
+               rel2.to: "base";
+               rel2.offset: 0 0;
+               image {
+                  normal: "slv_bg_over.png";
+                  border: 3 3 3 3;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+           type: RECT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+               visible: 0;
+              rel1.to: "elm.swallow.bar";
+              rel2.to: "elm.swallow.bar";
+              color: 0 0 0 0;
+           }
+        }
+        part { name: "elm.swallow.bar";
+           type: SWALLOW;
+            scale: 1;
+           description { state: "default" 0.0;
+              min: 24 48;
+              max: 24 9999;
+              align: 0.5 1.0;
+              rel1 {
+                  to_y: "elm.text";
+                  relative: 0.0 1.0;
+                  offset: 0 10;
+               }
+              rel2 {
+                  to_y: "elm.units";
+                  relative: 1.0 0.0;
+                  offset: -1 -8;
+               }
+           }
+        }
+        part { name: "elm.swallow.icon";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              visible: 0;
+              align: 0.5 0.0;
+              rel1 {
+                  offset: 0 4;
+                  to_x: "elm.swallow.bar";
+               }
+              rel2 {
+                  offset: -1 3;
+                  relative: 1.0 0.0;
+                  to_x: "elm.swallow.bar";
+               }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              aspect_preference: HORIZONTAL;
+              rel2.offset: -1 4;
+           }
+        }
+         part { name: "elm.text";
+           type: TEXT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+               fixed: 0 1;
+               align: 0.5 0.0;
+              rel1.to_y: "elm.swallow.icon";
+              rel1.relative: 0.0 1.0;
+               rel1.offset: 0 -1;
+              rel2.to_y: "elm.swallow.icon";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -1 -1;
+              color: 0 0 0 255;
+              text {
+                 font: "Sans,Edje-Vera";
+                 size: 10;
+                 min: 0 0;
+                 align: 0.5 0.0;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+               rel1.offset: 4 0;
+               rel2.offset: -5 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 255 128 128 128;
+              visible: 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+        part {
+            name: "elm.swallow.end";
+            type: SWALLOW;
+           description {
+               state: "default" 0.0;
+              visible: 0;
+              align: 0.5 1.0;
+              rel1 {
+                  offset: 0 -4;
+                  relative: 0.0 1.0;
+                  to_x: "elm.swallow.bar";
+               }
+              rel2 {
+                  offset: -1 -3;
+                  to_x: "elm.swallow.bar";
+               }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              aspect: 1.0 1.0;
+              aspect_preference: HORIZONTAL;
+              rel2.offset: -1 -4;
+           }
+        }
+         part { name: "units";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               rel1 {
+                  to: "elm.units";
+                  offset: -8 0;
+               }
+               rel2 {
+                  to: "elm.units";
+                  offset: 7 8;
+               }
+               image {
+                  normal: "slv_units.png";
+                  border: 8 8 0 9;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "elm.units";
+           type: TEXT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+               fixed: 1 1;
+              align: 0.5 1.0;
+              rel1.relative: 0.0 0.0;
+              rel1.to_y: "elm.swallow.end";
+              rel1.offset: 8 0;
+              rel2.relative: 1.0 0.0;
+              rel2.to_y: "elm.swallow.end";
+              rel2.offset: -9 0;
+              color: 0 0 0 255;
+              text {
+                 font: "Sans,Edje-Vera";
+                 size: 10;
+                 min: 0 0;
+                 align: 0.5 0.0;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+               fixed: 1 1;
+              visible: 1;
+              text.min: 1 1;
+              rel1.offset: 8 -9;
+              rel2.offset: -9 -9;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color:  0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              fixed: 1 1;
+              visible: 1;
+              text.min: 1 1;
+              rel1.offset: 8 -9;
+              rel2.offset: -9 -9;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+           }
+        }
+         part { name: "elm.dragable.slider";
+            type: RECT;
+            mouse_events: 0;
+            scale: 1;
+            dragable {
+               x: 0 0 0;
+               y: 1 1 0;
+               confine: "bg";
+            }
+            description { state: "default" 0.0;
+               min: 24 0;
+               max: 24 0;
+               fixed: 1 1;
+               rel1 {
+                  relative: 0.5  0.0;
+                  to_y: "bg";
+               }
+               rel2 {
+                  relative: 0.5  1.0;
+                  to_y: "bg";
+               }
+               color: 0 0 0 0;
+            }
+         }
+         part { name: "button_events";
+           type: RECT;
+           dragable {
+              events: "elm.dragable.slider";
+           }
+            mouse_events: 1;
+           description { state: "default" 0.0;
+               fixed: 1 1;
+               min: 16 16;
+               aspect: 1.0 1.0;
+               aspect_preference: HORIZONTAL;
+              rel1.to_y: "elm.dragable.slider";
+              rel2.to_y: "elm.dragable.slider";
+              color: 0 0 0 0;
+           }
+        }
+         part { name: "button0";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               max: 17 999;
+               min: 17 24;
+               rel1.to: "elm.dragable.slider";
+               rel2.to: "elm.dragable.slider";
+               image {
+                  normal: "sl_bt_0.png";
+                  border: 5 5 5 10;
+               }
+               fill.smooth: 0;
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               image {
+                  normal: "sl_bt_3.png";
+                  border: 5 5 5 10;
+               }
+            }
+         }
+         part { name: "button1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button0";
+               rel2 {
+                  to: "button0";
+                  relative: 1.0 0.5;
+                  offset: -1 -5;
+               }
+               image {
+                  normal: "sl_bt_1.png";
+                  border: 5 5 5 0;
+               }
+            }
+         }
+         part { name: "button2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button0";
+               rel2.to: "button0";
+               image {
+                  normal: "sl_bt_2.png";
+                  border: 5 5 5 10;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "button3";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               min: 8 32;
+               align: 1.0 0.5;
+               rel1 {
+                  to_x: "elm.indicator";
+                  to_y: "button4";
+                  relative: 0.0 0.0;
+                  offset: -7 0;
+               }
+               rel2 {
+                  to: "button4";
+                  relative: 0.0 1.0;
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "sl_bt2_0_0.png";
+                  border: 6 0 6 12;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "button4";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               max: 15 999;
+               min: 15 32;
+               fixed: 1 1;
+               rel1 {
+                  to_x: "button0";
+                  to_y: "elm.indicator";
+                  offset: 0 -7;
+               }
+               rel2.to: "button0";
+               image {
+                  normal: "sl_bt2_0_1.png";
+                  border: 0 0 6 12;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "button5";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               min: 8 32;
+               align: 0.0 0.5;
+               rel1 {
+                  to: "button4";
+                  relative: 1.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to_x: "elm.indicator";
+                  to_y: "button4";
+                  relative: 1.0 1.0;
+                  offset: 6 -1;
+               }
+               image {
+                  normal: "sl_bt2_0_2.png";
+                  border: 0 6 6 12;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "elm.indicator";
+           type: TEXT;
+           mouse_events: 0;
+            effect: SOFT_SHADOW;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+               fixed: 1 1;
+               align: 0.5 1.0;
+              rel1 {
+                  to: "button0";
+                  relative: 0.0 -1.0;
+                  offset: 0 0;
+               }
+              rel2 {
+                  to: "button0";
+                  relative: 1.0 -1.0;
+                  offset: -1 0;
+               }
+              color: 224 224 224 255;
+              color3: 0 0 0 64;
+              text {
+                 font:     "Sans,Edje-Vera";
+                 size:     10;
+                 min:      0 0;
+                 align:    0.5 0.5;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+               rel1.offset: 0 -1;
+               rel2.offset: -1 -1;
+           }
+        }
+         part { name: "button6";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               rel1.to: "button3";
+               rel2 {
+                  to: "button5";
+                  relative: 1.0 0.3;
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "sl_bt2_1.png";
+                  border: 5 5 5 0;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+         part { name: "button7";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+              visible: 0;
+               rel1.to: "button3";
+               rel2.to: "button5";
+               image {
+                  normal: "sl_bt2_2.png";
+                  border: 5 5 5 0;
+                  middle: 0;
+               }
+               fill.smooth: 0;
+            }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+            }
+         }
+            part { name: "disabler";
+               type: RECT;
+               description { state: "default" 0.0;
+                  color: 0 0 0 0;
+                  visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                  inherit: "default" 0.0;
+                  visible: 1;
+               }
+            }
+         }
+
+      programs {
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.text";
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.text";
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.swallow.icon";
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.icon";
+        }
+        program { name: "end_show";
+           signal: "elm,state,end,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.swallow.end";
+        }
+        program { name: "end_hide";
+           signal: "elm,state,end,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.end";
+        }
+        program { name: "units_show";
+           signal: "elm,state,units,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.units";
+           target: "units";
+        }
+        program { name: "units_hide";
+           signal: "elm,state,units,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.units";
+           target: "units";
+        }
+        program { name: "invert_on";
+           signal: "elm,state,inverted,on";
+           source: "elm";
+           action:  STATE_SET "inverted" 0.0;
+           target: "level";
+           target: "level2";
+        }
+        program { name: "invert_off";
+           signal: "elm,state,inverted,off";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "level";
+           target: "level2";
+        }
+        program { name: "set_val_show";
+           signal: "elm,state,val,show";
+           source: "elm";
+           script {
+               set_value_show();
+           }
+        }
+        program { name: "set_val_hide";
+           signal: "elm,state,val,hide";
+           source: "elm";
+           script {
+               set_value_hide();
+           }
+        }
+        program { name: "val_show";
+           signal: "mouse,down,*";
+           source: "elm.dragable.slider";
+           script {
+               thumb_down();
+           }
+        }
+        program { name: "val_hide";
+           signal: "mouse,up,*";
+           source: "elm.dragable.slider";
+           script {
+               thumb_up();
+           }
+        }
+        program {
+           name:   "go_disabled";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "button0";
+           target: "disabler";
+           after: "disable_text";
+        }
+        program { name: "disable_text";
+           script {
+           new st[31];
+           new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                 set_state(PART:"elm.text", "disabled_visible", 0.0);
+              else
+                 set_state(PART:"elm.text", "disabled", 0.0);
+
+              get_state(PART:"elm.units", st, 30, vl);
+              if (!strcmp(st, "visible")) 
+                 set_state(PART:"elm.units", "disabled_visible", 0.0);
+              else 
+                 set_state(PART:"elm.units", "disabled", 0.0);
+
+              get_state(PART:"level2", st, 30, vl);
+              if (!strcmp(st, "inverted")) 
+               {
+                 set_state(PART:"level", "disabled_inverted", 0.0);
+                 set_state(PART:"level2", "disabled_inverted", 0.0);
+               }
+              else 
+               {
+                 set_state(PART:"level", "disabled", 0.0);
+                 set_state(PART:"level2", "disabled", 0.0);
+               }
+           }
+        }
+
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "button0";
+           target: "disabler";
+           after: "enable_text";
+        }
+        program { name: "enable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                 set_state(PART:"elm.text", "visible", 0.0);
+              else
+                 set_state(PART:"elm.text", "default", 0.0);
+
+              get_state(PART:"elm.units", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                 set_state(PART:"elm.units", "visible", 0.0);
+              else
+                 set_state(PART:"elm.units", "default", 0.0);
+     
+              get_state(PART:"level2", st, 30, vl);
+              if (!strcmp(st, "disabled_inverted"))
+               {
+                 set_state(PART:"level", "inverted", 0.0);
+                 set_state(PART:"level2", "inverted", 0.0);
+               }
+              else
+               {
+                 set_state(PART:"level", "default", 0.0);
+                 set_state(PART:"level2", "default", 0.0);
+               }
+           }
+        }
+      }
+   }
+
+////////////////////////////////////////////////////////////////////////////////
+// actionslider
+////////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/actionslider/base/default";
+
+      images {
+         image: "shelf_inset.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "bt_bases.png" COMP;
+         image: "bt_basew.png" COMP;
+         image: "bt_hilightw.png" COMP;
+      }
+
+      parts {
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               min: 75 25;
+               rel1.offset: 1 1;
+               rel2.offset: -2 -2;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "conf_over";
+            mouse_events:  0;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               image {
+                  normal: "shelf_inset.png";
+                  border: 7 7 7 7;
+                  middle: 0;
+               }
+               fill.smooth : 0;
+            }
+         }
+         part { name: "icon.dragable.area";
+           type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               rel1.to: "base";
+               rel2.to: "base";
+            }
+         }
+         part { name: "elm.text.left";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.05 0.5;
+                  min: 1 1;
+               }
+            }
+         }
+         part { name: "elm.text.center";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.5 0.5;
+                  min: 1 1;
+               }
+            }
+         }
+         part { name: "elm.text.right";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.95 0.5;
+                  min: 1 1;
+               }
+            }
+         }
+         part { name: "elm.drag_button_base";
+            type: SWALLOW;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               min: 50 25;
+               align: 0.5 0.5;
+               rel1.to: "icon.dragable.area";
+               rel2 {
+                  relative: 0.0 1.0;
+                  to: "icon.dragable.area";
+               }
+            }
+            dragable {
+               confine: "icon.dragable.area";
+               x: 1 1 0;
+               y: 0 0 0;
+            }
+         }
+         part { name: "elm.drag_button";
+            type: RECT;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 50 25;
+               color: 255 255 255 0;
+               rel1.to_x: "elm.drag_button_base";
+               rel1.to_y: "icon.dragable.area";
+               rel2.to_x: "elm.drag_button_base";
+               rel2.to_y: "icon.dragable.area";
+            }
+            dragable {
+               events: "elm.drag_button_base";
+            }
+         }
+         part { name: "button0";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button2";
+               rel1.offset: -4 -4;
+               rel2.to: "button2";
+               rel2.offset: 3 3;
+               image {
+                  normal: "bt_bases.png";
+                  border: 11 11 11 11;
+                  middle: SOLID;
+               }
+               color: 255 255 255 128;
+            }
+         }
+         part { name: "button2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.drag_button";
+               rel2.to: "elm.drag_button";
+               image {
+                  normal: "bt_basew.png";
+                  border: 7 7 7 7;
+                  middle: SOLID;
+               }
+               color: 255 255 255 210;
+            }
+         }
+         part { name: "button3";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button2";
+               rel2.to: "button2";
+               rel2.relative: 1.0 0.5;
+               image {
+                  normal: "bt_hilightw.png";
+                  border: 4 4 4 0;
+               }
+               color: 255 255 255 190;
+            }
+         }
+         part { name: "elm.text.indicator";
+            type: TEXT;
+            scale: 1;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1 {
+                  to: "elm.drag_button";
+                  offset: 5 0;
+               }
+               rel2 {
+                  to: "elm.drag_button";
+                  offset: -5 0;
+               }
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.5 0.5;
+                  min: 0 1;
+               }
+            }
+         }
+      }
+      programs {
+        program { name: "elm.drag_button,mouse,up";
+           signal: "mouse,up,1";
+           source: "elm.drag_button";
+            action: SIGNAL_EMIT "elm.drag_button,mouse,up" "";
+        }
+        program { name: "elm.drag_button,mouse,down";
+           signal: "mouse,down,1";
+           source: "elm.drag_button";
+            action: SIGNAL_EMIT "elm.drag_button,mouse,down" "";
+        }
+        program { name: "elm.drag_button,mouse,move";
+           signal: "mouse,move";
+           source: "elm.drag_button_base";
+            action: SIGNAL_EMIT "elm.drag_button,mouse,move" "";
+        }
+      }
+   }
+
+   group { name: "elm/actionslider/base/bar";
+
+      images {
+         image: "shelf_inset.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "bt_bases.png" COMP;
+         image: "bt_basew.png" COMP;
+         image: "bt_hilightw.png" COMP;
+      }
+
+      parts {
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               min: 150 30;
+               rel1.offset: 1 1;
+               rel2.offset: -2 -2;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "conf_over";
+            mouse_events:  0;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               image {
+                  normal: "shelf_inset.png";
+                  border: 7 7 7 7;
+                  middle: 0;
+               }
+               fill.smooth : 0;
+            }
+         }
+         part { name: "icon.dragable.area";
+           type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               rel1.to: "base";
+               rel2.to: "base";
+            }
+         }
+         part { name: "elm.text.left";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.05 0.5;
+                  min: 1 1;
+               }
+            }
+         }
+         part { name: "elm.text.center";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.5 0.5;
+                  min: 1 1;
+               }
+            }
+         }
+         part { name: "elm.text.right";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.95 0.5;
+                  min: 1 1;
+               }
+            }
+         }
+         part { name: "bar";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "base";
+               rel1.offset: 0 2;
+               rel2 {
+                  relative: 0 1;
+                  offset: 3 -3;
+                  to_x: "elm.drag_button_base";
+                  to_y: "base";
+               }
+               color: 0 0 0 180;
+            }
+         }
+         part { name: "elm.drag_button_base";
+            type: SWALLOW;
+            mouse_events: 1;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               min: 50 25;
+               align: 0.5 0.5;
+               rel1.to: "icon.dragable.area";
+               rel2 {
+                  relative: 0.0 1.0;
+                  to: "icon.dragable.area";
+               }
+            }
+            dragable {
+               confine: "icon.dragable.area";
+               x: 1 1 0;
+               y: 0 0 0;
+            }
+         }
+         part { name: "elm.drag_button";
+            type: RECT;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 50 25;
+               color: 255 255 255 0;
+               rel1.to_x: "elm.drag_button_base";
+               rel1.to_y: "icon.dragable.area";
+               rel2.to_x: "elm.drag_button_base";
+               rel2.to_y: "icon.dragable.area";
+            }
+            dragable {
+               events: "elm.drag_button_base";
+            }
+         }
+         part { name: "button0";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button2";
+               rel1.offset: -4 -4;
+               rel2.to: "button2";
+               rel2.offset: 3 3;
+               image {
+                  normal: "bt_bases.png";
+                  border: 11 11 11 11;
+                  middle: SOLID;
+               }
+               color: 255 255 255 128;
+            }
+         }
+         part { name: "button2";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.drag_button";
+               rel2.to: "elm.drag_button";
+               image {
+                  normal: "bt_basew.png";
+                  border: 7 7 7 7;
+                  middle: SOLID;
+               }
+               color: 255 255 255 210;
+            }
+         }
+         part { name: "button3";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button2";
+               rel2.to: "button2";
+               rel2.relative: 1.0 0.5;
+               image {
+                  normal: "bt_hilightw.png";
+                  border: 4 4 4 0;
+               }
+               color: 255 255 255 190;
+            }
+         }
+         part { name: "elm.text.indicator";
+            type: TEXT;
+            scale: 1;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1 {
+                  to: "elm.drag_button";
+                  offset: 5 0;
+               }
+               rel2 {
+                  to: "elm.drag_button";
+                  offset: -5 0;
+               }
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  align: 0.5 0.5;
+                  min: 0 1;
+               }
+            }
+         }
+      }
+      programs {
+        program { name: "elm.drag_button,mouse,up";
+           signal: "mouse,up,1";
+           source: "elm.drag_button";
+            action: SIGNAL_EMIT "elm.drag_button,mouse,up" "";
+        }
+        program { name: "elm.drag_button,mouse,down";
+           signal: "mouse,down,1";
+           source: "elm.drag_button";
+            action: SIGNAL_EMIT "elm.drag_button,mouse,down" "";
+        }
+        program { name: "elm.drag_button,mouse,move";
+           signal: "mouse,move";
+           source: "elm.drag_button_base";
+            action: SIGNAL_EMIT "elm.drag_button,mouse,move" "";
+        }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/genlist/item/default/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item/group_index/default";
+      alias: "elm/genlist/item_odd/group_index/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+         image: "group_index.png" COMP;
+      }
+      parts {
+         part {
+            name: "event";
+            type: RECT;
+            repeat_events: 0;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "group_index.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset: 4 -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0 0.0;
+                  offset: -1 4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0 1.0;
+                  offset: -1 -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0 0.0;
+                  offset: -5 4;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -5 -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x: "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset: 0 4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset: -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress/message/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.title.1 elm.title.2 elm.text";
+//      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      styles {
+        style { name: "genlist_textblock_style";
+          base: "font=Sans font_size=10 color=#000 wrap=char text_class=list_item";
+          tag:  "br" "\n";
+          tag:  "ps" "ps";
+          tag:  "tab" "\t";
+        }
+        style { name: "genlist_textblock_style2";
+          base: "font=Sans font_size=10 color=#fff wrap=char text_class=list_item";
+          tag:  "br" "\n";
+          tag:  "ps" "ps";
+          tag:  "tab" "\t";
+        }
+      }
+     parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.title.1";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               fixed: 0 1;
+//               min: 16 16;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.0;
+                  offset:   -5 4;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               align: 0.0 0.0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.0;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.title.2";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               fixed: 0 1;
+//               min: 16 16;
+               rel1 {
+                  to_y:     "elm.title.1";
+                  relative: 0.0  1.0;
+                  offset:   4 0;
+               }
+               rel2 {
+                  to_y:     "elm.title.1";
+                  relative: 1.0  1.0;
+                  offset:   -5 0;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               align: 0.0 0.0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.0;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXTBLOCK;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               fixed: 0 1;
+//               min: 16 16;
+               rel1 {
+                  to_y:     "elm.title.2";
+                  relative: 0.0  1.0;
+                  offset:   4 0;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5 -5;
+               }
+               align: 0.0 0.0;
+               text {
+                  style: "genlist_textblock_style";
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "genlist_textblock_style2";
+               }
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.title.1";
+            target:  "elm.title.2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.title.1";
+            target:  "elm.title.2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress_odd/message/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.title.1 elm.title.2 elm.text";
+//      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.title.1";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               fixed: 0 1;
+//               min: 16 16;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.0;
+                  offset:   -5 4;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               align: 0.0 0.0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.0;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.title.2";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               fixed: 0 1;
+//               min: 16 16;
+               rel1 {
+                  to_y:     "elm.title.1";
+                  relative: 0.0  1.0;
+                  offset:   4 0;
+               }
+               rel2 {
+                  to_y:     "elm.title.1";
+                  relative: 1.0  1.0;
+                  offset:   -5 0;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               align: 0.0 0.0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.0;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXTBLOCK;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               fixed: 0 1;
+//               min: 16 16;
+               rel1 {
+                  to_y:     "elm.title.2";
+                  relative: 0.0  1.0;
+                  offset:   4 0;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5 -5;
+               }
+               align: 0.0 0.0;
+               text {
+                  style: "genlist_textblock_style";
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               text {
+                  style: "genlist_textblock_style2";
+               }
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.title.1";
+            target:  "elm.title.2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.title.1";
+            target:  "elm.title.2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress/default/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_odd/default/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min:      16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress_odd/default/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min:      16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+//                  min: 1 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/tree/default/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+   group { name: "elm/genlist/tree_compress/default/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+   group { name: "elm/genlist/tree_odd/default/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+   group { name: "elm/genlist/tree_compress_odd/default/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/item/default_style/default";
+       styles
+       {
+           style { name: "genlist_style";
+               base: "font=Sans font_size=10 align=left valign=0.5 color=#000 text_class=list_item";
+               tag:  "br" "\n";
+               tag:  "ps" "ps";
+               tag:  "hilight" "+ font=Sans:style=Bold";
+               tag:  "b" "+ font=Sans:style=Bold";
+               tag:  "tab" "\t";
+           }
+           style { name: "genlist_selected_style";
+               base: "font=Sans font_size=10 align=left valign=0.5 color=#fff text_class=list_item";
+               tag:  "br" "\n";
+               tag:  "ps" "ps";
+               tag:  "hilight" "+ font=Sans:style=Bold";
+               tag:  "b" "+ font=Sans:style=Bold";
+               tag:  "tab" "\t";
+           }
+       }
+       data.item: "stacking" "above";
+       data.item: "selectraise" "on";
+       data.item: "labels" "elm.text";
+       data.item: "icons" "elm.swallow.icon elm.swallow.end";
+       data.item: "treesize" "20";
+       images {
+           image: "bt_sm_base1.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "ilist_1.png" COMP;
+           image: "ilist_item_shadow.png" COMP;
+       }
+       parts {
+           part {
+               name:           "event";
+               type:           RECT;
+               repeat_events: 1;
+               description {
+                   state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+           }
+           part {
+               name: "base_sh";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.0;
+                   min: 0 10;
+                   fixed: 1 1;
+                   rel1 {
+                       to: "base";
+                       relative: 0.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "base";
+                       relative: 1.0 1.0;
+                       offset: -1 0;
+                   }
+                   image {
+                       normal: "ilist_item_shadow.png";
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part {
+               name: "base";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   min: 16 28;
+                   image {
+                       normal: "ilist_1.png";
+                       border: 2 2 2 2;
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "bg";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -5 -5;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 4 4;
+                   }
+                   image {
+                       normal: "bt_sm_base1.png";
+                       border: 6 6 6 6;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -2 -2;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 1 1;
+                   }
+               }
+           }
+           part { name: "elm.swallow.pad";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       relative: 0.0  0.0;
+                       offset:   4    4;
+                   }
+                   rel2 {
+                       relative: 0.0  1.0;
+                       offset:   4   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.icon";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  0.0;
+                       offset:   -1    4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  1.0;
+                       offset:   -1   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.end";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 1.0 0.5;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   rel1 {
+                       relative: 1.0  0.0;
+                       offset:   -5    4;
+                   }
+                   rel2 {
+                       relative: 1.0  1.0;
+                       offset:   -5   -5;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               clip_to: "disclip";
+               type: TEXTBLOCK;
+               mouse_events: 0;
+               scale: 1;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.5;
+                   fixed: 0 1;
+                   rel1 {
+                       to_x: "elm.swallow.icon";
+                       to_y: "base";
+                       relative: 1.0  0.5;
+                       offset:   0 4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.end";
+                       to_y: "base";
+                       relative: 0.0  0.5;
+                       offset:   -1 -5;
+                   }
+                   text {
+                       style: "genlist_style";
+                       min: 1 1;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   text {
+                       style: "genlist_selected_style";
+                   }
+               }
+           }
+           part { name: "fg1";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "fg2";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "disclip";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 64;
+               }
+           }
+       }
+       programs {
+           // signal: elm,state,%s,active
+           //   a "check" item named %s went active
+           // signal: elm,state,%s,passive
+           //   a "check" item named %s went passive
+           // default is passive
+           program {
+               name:    "go_active";
+               signal:  "elm,state,selected";
+               source:  "elm";
+               action:  STATE_SET "selected" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+           }
+           program {
+               name:    "go_passive";
+               signal:  "elm,state,unselected";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+               transition: LINEAR 0.1;
+           }
+           program {
+               name:    "go_disabled";
+               signal:  "elm,state,disabled";
+               source:  "elm";
+               action:  STATE_SET "disabled" 0.0;
+               target:  "disclip";
+           }
+           program {
+               name:    "go_enabled";
+               signal:  "elm,state,enabled";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "disclip";
+           }
+       }
+   }
+   group { name: "elm/genlist/item_odd/default_style/default";
+       data.item: "stacking" "below";
+       data.item: "selectraise" "on";
+       data.item: "labels" "elm.text";
+       data.item: "icons" "elm.swallow.icon elm.swallow.end";
+       data.item: "treesize" "20";
+       images {
+           image: "bt_sm_base1.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "ilist_2.png" COMP;
+       }
+       parts {
+           part { name: "event";
+               type: RECT;
+               repeat_events: 1;
+               description {
+                   state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+           }
+           part {
+               name: "base";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   min: 16 28;
+                   image {
+                       normal: "ilist_2.png";
+                       border: 2 2 2 2;
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "bg";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -5 -5;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 4 4;
+                   }
+                   image {
+                       normal: "bt_sm_base1.png";
+                       border: 6 6 6 6;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -2 -2;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 1 1;
+                   }
+               }
+           }
+           part { name: "elm.swallow.pad";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       relative: 0.0  0.0;
+                       offset:   4    4;
+                   }
+                   rel2 {
+                       relative: 0.0  1.0;
+                       offset:   4   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.icon";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  0.0;
+                       offset:   -1    4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  1.0;
+                       offset:   -1   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.end";
+               clip_to: "disclip";
+               type:          SWALLOW;
+               description { state:    "default" 0.0;
+                   fixed: 1 0;
+                   align:    1.0 0.5;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   rel1 {
+                       relative: 1.0  0.0;
+                       offset:   -5    4;
+                   }
+                   rel2 {
+                       relative: 1.0  1.0;
+                       offset:   -5   -5;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               clip_to: "disclip";
+               type:           TEXTBLOCK;
+               mouse_events:   0;
+               scale: 1;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.5;
+                   fixed: 0 1;
+                   rel1 {
+                       to_x: "elm.swallow.icon";
+                       to_y: "base";
+                       relative: 1.0  0.5;
+                       offset:   0 4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.end";
+                       to_y: "base";
+                       relative: 0.0  0.5;
+                       offset:   -1 -5;
+                   }
+                   text {
+                       style: "genlist_style";
+                       min: 1 1;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   text {
+                       style: "genlist_selected_style";
+                   }
+               }
+           }
+           part { name: "fg1";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "fg2";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "disclip";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 64;
+               }
+           }
+       }
+       programs {
+           // signal: elm,state,%s,active
+           //   a "check" item named %s went active
+           // signal: elm,state,%s,passive
+           //   a "check" item named %s went passive
+           // default is passive
+           program {
+               name:    "go_active";
+               signal:  "elm,state,selected";
+               source:  "elm";
+               action:  STATE_SET "selected" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+           }
+           program {
+               name:    "go_passive";
+               signal:  "elm,state,unselected";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+               transition: LINEAR 0.1;
+           }
+           program {
+               name:    "go_disabled";
+               signal:  "elm,state,disabled";
+               source:  "elm";
+               action:  STATE_SET "disabled" 0.0;
+               target:  "disclip";
+           }
+           program {
+               name:    "go_enabled";
+               signal:  "elm,state,enabled";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "disclip";
+           }
+       }
+   }
+
+   group { name: "elm/genlist/tree/default_style/default";
+       data.item: "stacking" "above";
+       data.item: "selectraise" "on";
+       data.item: "labels" "elm.text";
+       data.item: "icons" "elm.swallow.icon elm.swallow.end";
+       data.item: "treesize" "20";
+       images {
+           image: "bt_sm_base1.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "ilist_1.png" COMP;
+           image: "ilist_item_shadow.png" COMP;
+           image: "icon_arrow_right.png" COMP;
+           image: "icon_arrow_down.png" COMP;
+       }
+       parts {
+           part {
+               name:           "event";
+               type:           RECT;
+               repeat_events: 1;
+               description {
+                   state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+           }
+           part {
+               name: "base_sh";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.0;
+                   min: 0 10;
+                   fixed: 1 1;
+                   rel1 {
+                       to: "base";
+                       relative: 0.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "base";
+                       relative: 1.0 1.0;
+                       offset: -1 0;
+                   }
+                   image {
+                       normal: "ilist_item_shadow.png";
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part {
+               name: "base";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   min: 16 28;
+                   image {
+                       normal: "ilist_1.png";
+                       border: 2 2 2 2;
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "bg";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -5 -5;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 4 4;
+                   }
+                   image {
+                       normal: "bt_sm_base1.png";
+                       border: 6 6 6 6;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -2 -2;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 1 1;
+                   }
+               }
+           }
+           part { name: "elm.swallow.pad";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       relative: 0.0  0.0;
+                       offset:   4    4;
+                   }
+                   rel2 {
+                       relative: 0.0  1.0;
+                       offset:   4   -5;
+                   }
+               }
+           }
+           part { name: "arrow";
+               clip_to: "disclip";
+               ignore_flags: ON_HOLD;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   aspect: 1.0 1.0;
+                   rel1 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  0.0;
+                       offset:   -1    4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  1.0;
+                       offset:   -1   -5;
+                   }
+                   image.normal: "icon_arrow_right.png";
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "icon_arrow_down.png";
+               }
+           }
+           part { name: "elm.swallow.icon";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       to_x: "arrow";
+                       relative: 1.0  0.0;
+                       offset:   4    4;
+                   }
+                   rel2 {
+                       to_x: "arrow";
+                       relative: 1.0  1.0;
+                       offset:   4   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.end";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 1.0 0.5;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   rel1 {
+                       relative: 1.0  0.0;
+                       offset:   -5    4;
+                   }
+                   rel2 {
+                       relative: 1.0  1.0;
+                       offset:   -5   -5;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               clip_to: "disclip";
+               type:           TEXTBLOCK;
+               effect:         SOFT_SHADOW;
+               mouse_events:   0;
+               scale: 1;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.5;
+                   fixed: 0 1;
+                   rel1 {
+                       to_x:     "elm.swallow.icon";
+                       to_y: "base";
+                       relative: 1.0  0.5;
+                       offset:   0 4;
+                   }
+                   rel2 {
+                       to_x:     "elm.swallow.end";
+                       to_y: "base";
+                       relative: 0.0  0.5;
+                       offset:   -1 -5;
+                   }
+                   text {
+                       style: "genlist_style";
+                       min: 1 1;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   text {
+                       style: "genlist_selected_style";
+                   }
+               }
+           }
+           part { name: "fg1";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "fg2";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "disclip";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 64;
+               }
+           }
+       }
+       programs {
+           // signal: elm,state,%s,active
+           //   a "check" item named %s went active
+           // signal: elm,state,%s,passive
+           //   a "check" item named %s went passive
+           // default is passive
+           program {
+               name:    "go_active";
+               signal:  "elm,state,selected";
+               source:  "elm";
+               action:  STATE_SET "selected" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+           }
+           program {
+               name:    "go_passive";
+               signal:  "elm,state,unselected";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+               transition: LINEAR 0.1;
+           }
+           program {
+               name:    "go_disabled";
+               signal:  "elm,state,disabled";
+               source:  "elm";
+               action:  STATE_SET "disabled" 0.0;
+               target:  "disclip";
+           }
+           program {
+               name:    "go_enabled";
+               signal:  "elm,state,enabled";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "disclip";
+           }
+           program {
+               name:    "expand";
+               signal:  "mouse,up,1";
+               source:  "arrow";
+               action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+           }
+           program {
+               name:    "go_expanded";
+               signal:  "elm,state,expanded";
+               source:  "elm";
+               action:  STATE_SET "active" 0.0;
+               target:  "arrow";
+           }
+           program {
+               name:    "go_contracted";
+               signal:  "elm,state,contracted";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "arrow";
+           }
+       }
+   }
+   group { name: "elm/genlist/tree_odd/default_style/default";
+       data.item: "stacking" "below";
+       data.item: "selectraise" "on";
+       data.item: "labels" "elm.text";
+       data.item: "icons" "elm.swallow.icon elm.swallow.end";
+       data.item: "treesize" "20";
+       images {
+           image: "bt_sm_base1.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "ilist_2.png" COMP;
+           image: "icon_arrow_right.png" COMP;
+           image: "icon_arrow_down.png" COMP;
+       }
+       parts {
+           part {
+               name:           "event";
+               type:           RECT;
+               repeat_events: 1;
+               description {
+                   state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+           }
+           part {
+               name: "base";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   min: 16 28;
+                   image {
+                       normal: "ilist_2.png";
+                       border: 2 2 2 2;
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "bg";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -5 -5;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 4 4;
+                   }
+                   image {
+                       normal: "bt_sm_base1.png";
+                       border: 6 6 6 6;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -2 -2;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 1 1;
+                   }
+               }
+           }
+           part { name: "elm.swallow.pad";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       relative: 0.0  0.0;
+                       offset:   4    4;
+                   }
+                   rel2 {
+                       relative: 0.0  1.0;
+                       offset:   4   -5;
+                   }
+               }
+           }
+           part { name: "arrow";
+               clip_to: "disclip";
+               ignore_flags: ON_HOLD;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   aspect: 1.0 1.0;
+                   rel1 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  0.0;
+                       offset:   -1    4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  1.0;
+                       offset:   -1   -5;
+                   }
+                   image.normal: "icon_arrow_right.png";
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "icon_arrow_down.png";
+               }
+           }
+           part { name: "elm.swallow.icon";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       to_x: "arrow";
+                       relative: 1.0  0.0;
+                       offset:   4    4;
+                   }
+                   rel2 {
+                       to_x: "arrow";
+                       relative: 1.0  1.0;
+                       offset:   4   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.end";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 1.0 0.5;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   rel1 {
+                       relative: 1.0  0.0;
+                       offset:   -5    4;
+                   }
+                   rel2 {
+                       relative: 1.0  1.0;
+                       offset:   -5   -5;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               clip_to: "disclip";
+               type:           TEXTBLOCK;
+               effect:         SOFT_SHADOW;
+               mouse_events:   0;
+               scale: 1;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.5;
+                   fixed: 0 1;
+                   rel1 {
+                       to_x:     "elm.swallow.icon";
+                       to_y: "base";
+                       relative: 1.0  0.5;
+                       offset:   0 4;
+                   }
+                   rel2 {
+                       to_x:     "elm.swallow.end";
+                       to_y: "base";
+                       relative: 0.0  0.5;
+                       offset:   -1 -5;
+                   }
+                   text {
+                       style: "genlist_style";
+                       min: 1 1;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   text {
+                       style: "genlist_selected_style";
+                   }
+               }
+           }
+           part { name: "fg1";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "fg2";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "disclip";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 64;
+               }
+           }
+       }
+       programs {
+           // signal: elm,state,%s,active
+           //   a "check" item named %s went active
+           // signal: elm,state,%s,passive
+           //   a "check" item named %s went passive
+           // default is passive
+           program {
+               name:    "go_active";
+               signal:  "elm,state,selected";
+               source:  "elm";
+               action:  STATE_SET "selected" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+           }
+           program {
+               name:    "go_passive";
+               signal:  "elm,state,unselected";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+               transition: LINEAR 0.1;
+           }
+           program {
+               name:    "go_disabled";
+               signal:  "elm,state,disabled";
+               source:  "elm";
+               action:  STATE_SET "disabled" 0.0;
+               target:  "disclip";
+           }
+           program {
+               name:    "go_enabled";
+               signal:  "elm,state,enabled";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "disclip";
+           }
+           program {
+               name:    "expand";
+               signal:  "mouse,up,1";
+               source:  "arrow";
+               action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+           }
+           program {
+               name:    "go_expanded";
+               signal:  "elm,state,expanded";
+               source:  "elm";
+               action:  STATE_SET "active" 0.0;
+               target:  "arrow";
+           }
+           program {
+               name:    "go_contracted";
+               signal:  "elm,state,contracted";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "arrow";
+           }
+       }
+   }
+
+
+   group { name: "elm/genlist/item/double_label/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress/double_label/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_odd/double_label/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress_odd/double_label/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type:          SWALLOW;
+            description { state:    "default" 0.0;
+               fixed: 1 0;
+               align:    1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/tree/double_label/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+   group { name: "elm/genlist/tree_compress/double_label/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+   group { name: "elm/genlist/tree_odd/double_label/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/item/icon_top_text_bottom/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.5 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 0.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_y:     "elm.swallow.icon";
+                  relative: 0.0  1.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_odd/icon_top_text_bottom/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.5 0.5;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 0.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min:      16 16;
+               rel1 {
+                  to_y:     "elm.swallow.icon";
+                  relative: 0.0  1.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/tree/icon_top_text_bottom/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.5 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -4   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_y:     "elm.swallow.icon";
+                  relative: 0.0  1.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+   group { name: "elm/genlist/tree_odd/icon_top_text_bottom/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.5 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -4   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_y:     "elm.swallow.icon";
+                  relative: 0.0  1.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+//                  min: 0 1;
+                  align: 0.5 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/check/base/default";
+      images {
+         image: "check_base.png" COMP;
+        image: "check.png" COMP;
+        image: "check2.png" COMP;
+      }
+      parts {
+         part { name: "bg";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.offset: 1 1;
+              rel2.relative: 0.0 1.0;
+              rel2.offset: 1 -2;
+              align: 0.0 0.5;
+              min: 16 16;
+              max: 16 16;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+               image {
+                  normal: "check_base.png";
+                  border: 5 5 5 5;
+                  middle: 0;
+               }
+               fill.smooth : 0;
+           }
+        }
+         part { name: "check";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+               rel1 {
+                  to: "bg";
+                  offset: 1 1;
+               }
+               rel2 {
+                  to: "bg";
+                  offset: -2 -2;
+               }
+               visible: 0;
+               color: 255 255 255 255;
+               image.normal: "check.png";
+           }
+           description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+               visible: 0;
+              color: 128 128 128 128;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+              visible: 1;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 0;
+              visible: 0;
+              align: 0.0 0.5;
+          rel1.to_x: "bg";
+              rel1.relative: 1.0 0.0;
+              rel1.offset: 1 1;
+          rel2.to_x: "bg";
+              rel2.offset: 1 -2;
+              rel2.relative: 1.0 1.0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+          fixed: 1 0;
+              visible: 1;
+              aspect: 1.0 1.0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+          fixed: 1 0;
+              visible: 1;
+              aspect: 1.0 1.0;
+           }
+        }
+         part { name: "elm.text";
+           type: TEXT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to_x: "elm.swallow.content";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: 1 1;
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -2 -2;
+              color: 0 0 0 255;
+              text {
+                 font: "Sans,Edje-Vera";
+                 size: 10;
+                 min: 0 1;
+                 align: 0.0 0.5;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+         part { name: "events";
+           type: RECT;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+        }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program { name: "click";
+           signal: "mouse,up,1";
+           source: "events";
+            action: SIGNAL_EMIT "elm,action,check,toggle" "";
+        }
+        program { name: "check_on";
+           signal: "elm,state,check,on";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "check";
+        }
+        program { name: "check_off";
+           signal: "elm,state,check,off";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "check";
+        }
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.text";
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.text";
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "disable";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "disabler";
+            after: "disable_text";
+        }
+         program { name: "disable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.text", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.text", "disabled", 0.0);
+
+               get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "disabled", 0.0);
+
+               get_state(PART:"check", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"check", "disabled_visible", 0.0);
+              else
+                set_state(PART:"check", "disabled", 0.0);
+           }
+         }
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "disabler";
+            after: "enable_text";
+        }
+         program { name: "enable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                set_state(PART:"elm.text", "visible", 0.0);
+              else
+                set_state(PART:"elm.text", "default", 0.0);
+
+               get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "default", 0.0);
+
+               get_state(PART:"check", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"check", "visible", 0.0);
+              else
+                set_state(PART:"check", "default", 0.0);
+           }
+         }
+      }
+   }
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/radio/base/default";
+      images {
+         image: "radio_base.png" COMP;
+        image: "radio.png" COMP;
+        image: "radio2.png" COMP;
+      }
+      parts {
+         part { name: "bg";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.offset: 1 1;
+              rel2.relative: 0.0 1.0;
+              rel2.offset: 1 -2;
+              align: 0.0 0.5;
+              min: 16 16;
+              max: 16 16;
+              aspect: 1.0 1.0;
+              aspect_preference: VERTICAL;
+               image.normal: "radio_base.png";
+           }
+        }
+         part { name: "radio";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               visible: 0;
+               image.normal: "radio.png";
+           }
+           description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+               fixed: 1 0;
+              visible: 0;
+              align: 0.0 0.5;
+               color: 0 0 0 0;
+               rel1.to_x: "bg";
+               rel1.relative: 1.0 0.0;
+              rel1.offset: 1 1;
+               rel2.to_x: "bg";
+              rel2.relative: 1.0 1.0;
+              rel2.offset: 2 -2;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+               color: 255 255 255 255;
+              aspect: 1.0 1.0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 128;
+              visible: 1;
+              aspect: 1.0 1.0;
+           }
+        }
+         part { name: "elm.text";
+           type: TEXT;
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              visible: 0;
+              rel1.to_x: "elm.swallow.content";
+              rel1.relative: 1.0 0.0;
+               rel1.offset: 1 1;
+              rel2.relative: 1.0 1.0;
+              rel2.offset: -2 -2;
+              color: 0 0 0 255;
+              text {
+                 font: "Sans,Edje-Vera";
+                 size: 10;
+                 min: 0 0;
+                 align: 0.0 0.5;
+              }
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+              text.min: 1 1;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+           }
+           description { state: "disabled_visible" 0.0;
+              inherit: "default" 0.0;
+              color: 0 0 0 128;
+              color3: 0 0 0 0;
+              visible: 1;
+              text.min: 1 1;
+           }
+        }
+         part { name: "events";
+           type: RECT;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+        }
+        part { name: "disabler";
+           type: RECT;
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+              visible: 0;
+           }
+           description { state: "disabled" 0.0;
+              inherit: "default" 0.0;
+              visible: 1;
+           }
+        }
+      }
+      programs {
+        program { name: "click";
+           signal: "mouse,up,1";
+           source: "events";
+            action: SIGNAL_EMIT "elm,action,radio,toggle" "";
+        }
+        program { name: "radio_on";
+           signal: "elm,state,radio,on";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "radio";
+        }
+        program { name: "radio_off";
+           signal: "elm,state,radio,off";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "radio";
+        }
+        program { name: "text_show";
+           signal: "elm,state,text,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.text";
+        }
+        program { name: "text_hide";
+           signal: "elm,state,text,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.text";
+        }
+        program { name: "icon_show";
+           signal: "elm,state,icon,visible";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "icon_hide";
+           signal: "elm,state,icon,hidden";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "elm.swallow.content";
+        }
+        program { name: "disable";
+           signal: "elm,state,disabled";
+           source: "elm";
+           action: STATE_SET "disabled" 0.0;
+           target: "disabler";
+            after: "disable_text";
+        }
+         program { name: "disable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.text", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.text", "disabled", 0.0);
+
+               get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "disabled_visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "disabled", 0.0);
+           }
+         }
+        program { name: "enable";
+           signal: "elm,state,enabled";
+           source: "elm";
+           action: STATE_SET "default" 0.0;
+           target: "disabler";
+            after: "enable_text";
+        }
+         program { name: "enable_text";
+           script {
+              new st[31];
+              new Float:vl;
+              get_state(PART:"elm.text", st, 30, vl);
+              if (!strcmp(st, "disabled_visible"))
+                set_state(PART:"elm.text", "visible", 0.0);
+              else
+                set_state(PART:"elm.text", "default", 0.0);
+
+               get_state(PART:"elm.swallow.content", st, 30, vl);
+              if (!strcmp(st, "visible"))
+                set_state(PART:"elm.swallow.content", "visible", 0.0);
+              else
+                set_state(PART:"elm.swallow.content", "default", 0.0);
+           }
+         }
+      }
+   }
+   group { name: "elm/genlist/tree_compress_odd/double_label/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text elm.text.sub";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      data.item: "treesize" "20";
+//      data.item: "states" "";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+         image: "icon_arrow_right.png" COMP;
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "arrow";
+            clip_to: "disclip";
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               aspect: 1.0 1.0;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+               image.normal: "icon_arrow_right.png";
+            }
+            description { state: "active" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  to_x: "arrow";
+                  relative: 1.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  to_x: "arrow";
+                  relative: 1.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.5;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel1 {
+                  relative: 1.0  0.0;
+                  offset:   -5    4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -5   -5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.0;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.sub";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+//               min: 16 16;
+               rel1 {
+                  to_x:     "elm.swallow.icon";
+                  relative: 1.0  0.5;
+                  offset:   0 4;
+               }
+               rel2 {
+                  to_x:     "elm.swallow.end";
+                  relative: 0.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+//                  min: 1 1;
+                  min: 0 1;
+                  align: 0.0 0.5;
+                  text_class: "list_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            target:  "elm.text.sub";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "expand";
+            signal:  "mouse,up,1";
+            source:  "arrow";
+            action:  SIGNAL_EMIT "elm,action,expand,toggle" "elm";
+         }
+         program {
+            name:    "go_expanded";
+            signal:  "elm,state,expanded";
+            source:  "elm";
+            action:  STATE_SET "active" 0.0;
+            target:  "arrow";
+         }
+         program {
+            name:    "go_contracted";
+            signal:  "elm,state,contracted";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "arrow";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/item_compress/media/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text.title elm.text.album-artist";
+      data.item: "treesize" "20";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name:           "event";
+            type:           RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.text.title";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.album-artist";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.5;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.album-artist";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.album-artist";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress_odd/media/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text.title elm.text.album-artist";
+      data.item: "treesize" "20";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.text.title";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.album-artist";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.5;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.album-artist";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.album-artist";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/item_compress/media-album/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text.title elm.text.trackno elm.text.length";
+      data.item: "states" "elm.state.trackno";
+      data.item: "treesize" "20";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      script {
+         public dot_visible;
+      }
+      parts {
+         part {
+            name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part {
+            name: "elm.text.trackno";
+            type: TEXT;
+            scale: 1;
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               color: 255 255 255 255;
+               align: 0.0 0.0;
+               fixed: 1 0;
+               rel1 {
+                  to_y: "elm.text.title";
+                  relative: 0.0 0.0;
+                  offset: 5 0;
+               }
+               rel2 {
+                  to_y: "elm.text.title";
+                  relative: 0.0 1.0;
+                  offset: 20 0;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 1.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part {
+            name: "dot";
+            type: TEXT;
+            scale: 1;
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               color: 255 255 255 255;
+               visible: 0;
+               fixed: 1 1;
+               align: 0.0 0.0;
+               rel1 {
+                  to_x: "elm.text.trackno";
+                  to_y: "elm.text.title";
+                  relative: 1.0 0.0;
+                  offset: 1 0;
+               }
+               rel2 {
+                  to_x: "elm.text.trackno";
+                  to_y: "elm.text.title";
+                  relative: 1.0 1.0;
+                  offset: 1 0;
+
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.0 0.5;
+                  text: ".";
+               }
+            }
+            description {
+               state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+               visible: 1;
+            }
+         }
+         programs {
+            program {
+               signal: "elm,state,elm.state.trackno,active";
+               source: "elm";
+               script {
+                  set_state(PART:"dot", "visible", 0.0);
+                  set_int(dot_visible, 1);
+               }
+            }
+         }
+         part { name: "elm.text.title";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to_x: "dot";
+                  relative: 0.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.length";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.5;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.trackno";
+            target:  "elm.text.length";
+            after:   "dot_active";
+         }
+         program {
+            name: "dot_active";
+            script {
+               if (get_int(dot_visible) == 1)
+                  set_state(PART:"dot", "selected", 0.0);
+            }
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.length";
+            target:  "elm.text.trackno";
+            transition: LINEAR 0.1;
+            after:   "dot_passive";
+         }
+         program {
+            name: "dot_passive";
+            script {
+               if (get_int(dot_visible) == 1)
+                  set_state(PART:"dot", "visible", 0.0);
+            }
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress_odd/media-album/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text.title elm.text.trackno elm.text.length";
+      data.item: "states" "elm.state.trackno";
+      data.item: "treesize" "20";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      script {
+         public dot_visible;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part {
+            name: "elm.text.trackno";
+            type: TEXT;
+            scale: 1;
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               color: 255 255 255 255;
+               align: 0.0 0.0;
+               fixed: 1 0;
+               rel1 {
+                  to_y: "elm.text.title";
+                  relative: 0.0 0.0;
+                  offset: 5 0;
+               }
+               rel2 {
+                  to_y: "elm.text.title";
+                  relative: 0.0 1.0;
+                  offset: 20 0;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 1.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part {
+            name: "dot";
+            type: TEXT;
+            scale: 1;
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               color: 255 255 255 255;
+               visible: 0;
+               fixed: 1 1;
+               align: 0.0 0.0;
+               rel1 {
+                  to_x: "elm.text.trackno";
+                  to_y: "elm.text.title";
+                  relative: 1.0 0.0;
+                  offset: 1 0;
+               }
+               rel2 {
+                  to_x: "elm.text.trackno";
+                  to_y: "elm.text.title";
+                  relative: 1.0 1.0;
+                  offset: 1 0;
+
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.0 0.5;
+                  text: ".";
+               }
+            }
+            description {
+               state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+               visible: 1;
+            }
+         }
+         programs {
+            program {
+               signal: "elm,state,elm.state.trackno,active";
+               source: "elm";
+               script {
+                  set_state(PART:"dot", "visible", 0.0);
+                  set_int(dot_visible, 1);
+               }
+            }
+         }
+         part { name: "elm.text.title";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to_x: "dot";
+                  relative: 1.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.length";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.5;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.length";
+            target:  "elm.text.trackno";
+            after:   "dot_active";
+         }
+         program {
+            name: "dot_active";
+            script {
+               if (get_int(dot_visible) == 1)
+                  set_state(PART:"dot", "selected", 0.0);
+            }
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.length";
+            target:  "elm.text.trackno";
+            transition: LINEAR 0.1;
+            after:   "dot_passive";
+         }
+         program {
+            name: "dot_passive";
+            script {
+               if (get_int(dot_visible) == 1)
+                  set_state(PART:"dot", "visible", 0.0);
+            }
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+
+   group { name: "elm/genlist/item_compress/media-preview/default";
+      data.item: "stacking" "above";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text.title elm.text.artist";
+      data.item: "icons" "elm.swallow.preview";
+      data.item: "treesize" "20";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part {
+            name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base_sh";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.preview";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               min: 68 68;
+               max: 68 68;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.text.title";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to_x:     "elm.swallow.preview";
+                  relative: 1.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.artist";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to_x:     "elm.swallow.preview";
+                  relative: 1.0  0.5;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.artist";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.artist";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/genlist/item_compress_odd/media-preview/default";
+      data.item: "stacking" "below";
+      data.item: "selectraise" "on";
+      data.item: "labels" "elm.text.title elm.text.artist";
+      data.item: "icons" "elm.swallow.preview";
+      data.item: "treesize" "20";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_2.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part {
+            name: "base";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               image {
+                  normal: "ilist_2.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   4    4;
+               }
+               rel2 {
+                  relative: 0.0  1.0;
+                  offset:   4   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.preview";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               min: 68 68;
+               max: 68 68;
+               rel1 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_x: "elm.swallow.pad";
+                  relative: 1.0  1.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.text.title";
+            clip_to: "disclip";
+            type:           TEXT;
+            effect:         SOFT_SHADOW;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to_x:     "elm.swallow.preview";
+                  relative: 1.0  0.0;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  0.5;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "elm.text.artist";
+            clip_to: "disclip";
+            type:           TEXT;
+            mouse_events:   0;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to_x:     "elm.swallow.preview";
+                  relative: 1.0  0.5;
+                  offset:   4 4;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset:   -1 -5;
+               }
+               color: 0 0 0 128;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 8;
+                  min: 0 1;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 128 128 128 255;
+               color3: 0 0 0 32;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program {
+            name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.artist";
+         }
+         program {
+            name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text.title";
+            target:  "elm.text.artist";
+            transition: LINEAR 0.1;
+         }
+         program {
+            name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program {
+            name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/pager/base/default";
+      data.item: "onshow" "raise";
+// other options
+//      data.item: "onhide" "lower";
+//      data.item: "onshow" "lower";
+      images {
+        image: "frame_1.png" COMP;
+        image: "frame_2.png" COMP;
+         image: "dia_grad.png" COMP;
+      }
+      parts {
+         part { name: "clip";
+            type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1 {
+                  to: "base";
+                  offset: -9999 -9999;
+               }
+              rel2 {
+                  to: "base";
+                  offset: 9999 9999;
+               }
+               color: 255 255 255 255;
+           }
+           description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 0;
+               visible: 0;
+           }
+        }
+         part { name: "base0";
+           mouse_events:  0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              image.normal: "dia_grad.png";
+              rel1.to: "over";
+              rel2.to: "over";
+               fill {
+                 smooth: 0;
+                 size {
+                    relative: 0.0 1.0;
+                     offset: 64 0;
+                 }
+              }
+           }
+        }
+        part { name: "base";
+           mouse_events:  0;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              image {
+                 normal: "frame_2.png";
+                 border: 5 5 32 26;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+           description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: -1.0 0.0;
+               rel2.relative: 0.0 1.0;
+           }
+           description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0.0 0.0;
+               rel2.relative: 1.0 1.0;
+           }
+        }
+         part { name: "over";
+           mouse_events:  0;
+            clip_to: "clip";
+           description { state:    "default" 0.0;
+              rel1 {
+                  to: "base";
+                  offset: 4 4;
+               }
+              rel2 {
+                  to: "base";
+                  offset: -5 -5;
+               }
+              image {
+                 normal: "frame_1.png";
+                 border: 2 2 28 22;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+            clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                  to: "base";
+                  offset: 8 8;
+               }
+              rel2 {
+                  to: "base";
+                  offset: -9 -9;
+               }
+           }
+        }
+      }
+      programs {
+        program { name: "push_start";
+           signal: "elm,action,push";
+           source: "elm";
+           action:  STATE_SET "hidden" 0.0;
+           target: "base";
+           target: "clip";
+            after: "show_start2";
+        }
+         program { name: "show_start";
+           signal: "elm,action,show";
+           source: "elm";
+           action:  STATE_SET "hidden" 0.0;
+           target: "base";
+           target: "clip";
+            after: "show_start2";
+        }
+         program { name: "show_start2";
+           action:  STATE_SET "visible" 0.0;
+            transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+            after: "show_end";
+        }
+         program { name: "show_end";
+            action: SIGNAL_EMIT "elm,action,show,finished" "";
+        }
+         program { name: "pop_start";
+           signal: "elm,action,pop";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "base";
+           target: "clip";
+            after: "hide_start2";
+        }
+         program { name: "hide_start";
+           signal: "elm,action,hide";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "base";
+           target: "clip";
+            after: "hide_start2";
+        }
+         program { name: "hide_start2";
+           action:  STATE_SET "hidden" 0.0;
+            transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+            after: "hide_end";
+        }
+         program { name: "hide_end";
+            action: SIGNAL_EMIT "elm,action,hide,finished" "";
+        }
+         program { name: "reset";
+           signal: "elm,action,reset";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "base";
+           target: "clip";
+        }
+      }
+   }
+
+   group { name: "elm/pager/base/slide";
+      images {
+        image: "frame_1.png" COMP;
+        image: "frame_2.png" COMP;
+        image: "dia_grad.png" COMP;
+      }
+      parts {
+        part { name: "clip";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1 {
+                 to: "base";
+                 offset: -9999 -9999;
+              }
+              rel2 {
+                 to: "base";
+                 offset: 9999 9999;
+              }
+              color: 255 255 255 255;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              inherit: "default" 0.0;
+              color: 255 255 255 0;
+              visible: 0;
+           }
+           description { state: "hidden2" 0.0;
+              inherit: "default" 0.0;
+              color: 255 255 255 0;
+              visible: 0;
+           }
+        }
+        part { name: "base0";
+           mouse_events:  0;
+           clip_to: "clip";
+           description { state: "default" 0.0;
+              image.normal: "dia_grad.png";
+              rel1.to: "over";
+              rel2.to: "over";
+              fill {
+                 smooth: 0;
+                 size {
+                    relative: 0.0 1.0;
+                    offset: 64 0;
+                 }
+              }
+           }
+        }
+        part { name: "base";
+           mouse_events:  0;
+           clip_to: "clip";
+           description { state: "default" 0.0;
+              image {
+                 normal: "frame_2.png";
+                 border: 5 5 32 26;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+           description { state: "hidden" 0.0;
+              inherit: "default" 0.0;
+              rel1.relative: -1.0 0.0;
+              rel2.relative: 0.0 1.0;
+           }
+           description { state: "hidden2" 0.0;
+              inherit: "default" 0.0;
+              rel1.relative: 1.0 0.0;
+              rel2.relative: 2.0 1.0;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+              rel1.relative: 0.0 0.0;
+              rel2.relative: 1.0 1.0;
+           }
+        }
+        part { name: "over";
+           mouse_events:  0;
+           clip_to: "clip";
+           description { state:    "default" 0.0;
+              rel1 {
+                 to: "base";
+                 offset: 4 4;
+              }
+              rel2 {
+                 to: "base";
+                 offset: -5 -5;
+              }
+              image {
+                 normal: "frame_1.png";
+                 border: 2 2 28 22;
+                 middle: 0;
+              }
+              fill.smooth : 0;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1 {
+                 to: "base";
+                 offset: 8 8;
+              }
+              rel2 {
+                 to: "base";
+                 offset: -9 -9;
+              }
+           }
+        }
+      }
+      programs {
+        program { name: "push_start";
+           signal: "elm,action,push";
+           source: "elm";
+           action:  STATE_SET "hidden2" 0.0;
+           target: "base";
+           target: "clip";
+           after: "show_start2";
+        }
+        program { name: "show_start";
+           signal: "elm,action,show";
+           source: "elm";
+           action:  STATE_SET "hidden" 0.0;
+           target: "base";
+           target: "clip";
+           after: "show_start2";
+        }
+        program { name: "show_start2";
+           action:  STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+           after: "show_end";
+        }
+        program { name: "show_end";
+           action: SIGNAL_EMIT "elm,action,show,finished" "";
+        }
+        program { name: "pop_start";
+           signal: "elm,action,pop";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "base";
+           target: "clip";
+           after: "pop_start2";
+        }
+        program { name: "pop_start2";
+           action:  STATE_SET "hidden2" 0.0;
+           transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+           after: "hide_end";
+        }
+        program { name: "hide_start";
+           signal: "elm,action,hide";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "base";
+           target: "clip";
+           after: "hide_start2";
+        }
+        program { name: "hide_start2";
+           action:  STATE_SET "hidden" 0.0;
+           transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+           after: "hide_end";
+        }
+        program { name: "hide_end";
+           action: SIGNAL_EMIT "elm,action,hide,finished" "";
+        }
+        program { name: "reset";
+           signal: "elm,action,reset";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "base";
+           target: "clip";
+        }
+      }
+   }
+   group { name: "elm/pager/base/slide_invisible";
+      parts {
+        part { name: "clip";
+           type: RECT;
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1 {
+                 to: "base";
+                 offset: -9999 -9999;
+           }
+              rel2 {
+                 to: "base";
+                 offset: 9999 9999;
+              }
+              color: 255 255 255 255;
+           }
+           description { state: "visible" 0.0;
+              inherit: "default" 0.0;
+           }
+           description { state: "hidden" 0.0;
+              inherit: "default" 0.0;
+              color: 255 255 255 0;
+              visible: 0;
+           }
+           description { state: "hidden2" 0.0;
+              inherit: "default" 0.0;
+              color: 255 255 255 0;
+              visible: 0;
+           }
+        }
+        part { name: "base";
+           type: RECT;
+           mouse_events:  0;
+           clip_to: "clip";
+           description { state: "default" 0.0;
+              color: 0 0 0 0;
+           }
+           description { state: "hidden" 0.0;
+              color: 0 0 0 0;
+              rel1.relative: -1.0 0.0;
+              rel2.relative: 0.0 1.0;
+           }
+           description { state: "hidden2" 0.0;
+              color: 0 0 0 0;
+              rel1.relative: 1.0 0.0;
+              rel2.relative: 2.0 1.0;
+           }
+           description { state: "visible" 0.0;
+              color: 0 0 0 0;
+              rel1.relative: 0.0 0.0;
+              rel2.relative: 1.0 1.0;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           clip_to: "clip";
+           description { state: "default" 0.0;
+              rel1.to: "base";
+              rel2.to: "base";
+           }
+        }
+      }
+      programs {
+        program { name: "push_start";
+           signal: "elm,action,push";
+           source: "elm";
+           action:  STATE_SET "hidden2" 0.0;
+           target: "base";
+           target: "clip";
+           after: "show_start2";
+        }
+        program { name: "show_start";
+           signal: "elm,action,show";
+           source: "elm";
+           action:  STATE_SET "hidden" 0.0;
+           target: "base";
+           target: "clip";
+           after: "show_start2";
+        }
+        program { name: "show_start2";
+           action:  STATE_SET "visible" 0.0;
+           transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+           after: "show_end";
+        }
+        program { name: "show_end";
+           action: SIGNAL_EMIT "elm,action,show,finished" "";
+        }
+        program { name: "pop_start";
+           signal: "elm,action,pop";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "base";
+           target: "clip";
+           after: "pop_start2";
+        }
+        program { name: "pop_start2";
+           action:  STATE_SET "hidden2" 0.0;
+           transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+           after: "hide_end";
+        }
+        program { name: "hide_start";
+           signal: "elm,action,hide";
+           source: "elm";
+           action:  STATE_SET "visible" 0.0;
+           target: "base";
+           target: "clip";
+           after: "hide_start2";
+        }
+        program { name: "hide_start2";
+           action:  STATE_SET "hidden" 0.0;
+           transition: DECELERATE 0.5;
+           target: "base";
+           target: "clip";
+           after: "hide_end";
+        }
+        program { name: "hide_end";
+           action: SIGNAL_EMIT "elm,action,hide,finished" "";
+        }
+        program { name: "reset";
+           signal: "elm,action,reset";
+           source: "elm";
+           action:  STATE_SET "default" 0.0;
+           target: "base";
+           target: "clip";
+        }
+      }
+   }
+
+   group { name: "elm/pager/base/fade";
+       data.item: "onshow" "raise";
+       // other options
+       //      data.item: "onhide" "lower";
+       //      data.item: "onshow" "lower";
+       images {
+           image: "frame_1.png" COMP;
+           image: "frame_2.png" COMP;
+           image: "dia_grad.png" COMP;
+       }
+       parts {
+           part { name: "clip_base";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: -9999 -9999;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: 9999 9999;
+                   }
+                   color: 255 255 255 120;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 0;
+                   visible: 0;
+               }
+           }
+           part { name: "clip";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: -9999 -9999;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: 9999 9999;
+                   }
+                   color: 255 255 255 255;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 0;
+                   visible: 0;
+               }
+           }
+           part { name: "base0";
+               mouse_events:  0;
+               clip_to: "clip_base";
+               description { state: "default" 0.0;
+                   image.normal: "dia_grad.png";
+                   rel1.to: "over";
+                   rel2.to: "over";
+                   fill {
+                       smooth: 0;
+                       size {
+                           relative: 0.0 1.0;
+                           offset: 64 0;
+                       }
+                   }
+               }
+           }
+           part { name: "base";
+               mouse_events:  0;
+               clip_to: "clip_base";
+               description { state: "default" 0.0;
+                   image {
+                       normal: "frame_2.png";
+                       border: 5 5 32 26;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "over";
+               mouse_events:  0;
+               clip_to: "clip";
+               description { state:    "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: 4 4;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: -5 -5;
+                   }
+                   image {
+                       normal: "frame_1.png";
+                       border: 2 2 28 22;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: 8 8;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: -9 -9;
+                   }
+               }
+           }
+       }
+       programs {
+           program { name: "push_start";
+               signal: "elm,action,push";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "show_start2";
+           }
+           program { name: "show_start";
+               signal: "elm,action,show";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "show_start2";
+           }
+           program { name: "show_start2";
+               action:  STATE_SET "visible" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+               target: "clip_base";
+               after: "show_end";
+           }
+           program { name: "show_end";
+               action: SIGNAL_EMIT "elm,action,show,finished" "";
+           }
+           program { name: "pop_start";
+               signal: "elm,action,pop";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "hide_start2";
+           }
+           program { name: "hide_start";
+               signal: "elm,action,hide";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "hide_start2";
+           }
+           program { name: "hide_start2";
+               action:  STATE_SET "hidden" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+               target: "clip_base";
+               after: "hide_end";
+           }
+           program { name: "hide_end";
+               action: SIGNAL_EMIT "elm,action,hide,finished" "";
+           }
+           program { name: "reset";
+               signal: "elm,action,reset";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "clip_base";
+               target: "clip";
+           }
+       }
+   }
+   group { name: "elm/pager/base/fade_translucide";
+       data.item: "onshow" "raise";
+       // other options
+       //      data.item: "onhide" "lower";
+       //      data.item: "onshow" "lower";
+       images {
+           image: "frame_1.png" COMP;
+           image: "frame_2.png" COMP;
+           image: "dia_grad.png" COMP;
+       }
+       parts {
+           part { name: "clip_base";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: -9999 -9999;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: 9999 9999;
+                   }
+                   color: 255 255 255 120;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 0;
+                   visible: 0;
+               }
+           }
+           part { name: "clip";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: -9999 -9999;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: 9999 9999;
+                   }
+                   color: 255 255 255 255;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 0;
+                   visible: 0;
+               }
+           }
+           part { name: "base0";
+               mouse_events:  0;
+               clip_to: "clip_base";
+               description { state: "default" 0.0;
+                   image.normal: "dia_grad.png";
+                   rel1.to: "over";
+                   rel2.to: "over";
+                   fill {
+                       smooth: 0;
+                       size {
+                           relative: 0.0 1.0;
+                           offset: 64 0;
+                       }
+                   }
+               }
+           }
+           part { name: "base";
+               mouse_events:  0;
+               clip_to: "clip_base";
+               description { state: "default" 0.0;
+                   image {
+                       normal: "frame_2.png";
+                       border: 5 5 32 26;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "over";
+               mouse_events:  0;
+               clip_to: "clip";
+               description { state:    "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: 4 4;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: -5 -5;
+                   }
+                   image {
+                       normal: "frame_1.png";
+                       border: 2 2 28 22;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "base";
+                       offset: 8 8;
+                   }
+                   rel2 {
+                       to: "base";
+                       offset: -9 -9;
+                   }
+               }
+           }
+       }
+       programs {
+           program { name: "push_start";
+               signal: "elm,action,push";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "show_start2";
+           }
+           program { name: "show_start";
+               signal: "elm,action,show";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "show_start2";
+           }
+           program { name: "show_start2";
+               action:  STATE_SET "visible" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+               target: "clip_base";
+               after: "show_end";
+           }
+           program { name: "show_end";
+               action: SIGNAL_EMIT "elm,action,show,finished" "";
+           }
+           program { name: "pop_start";
+               signal: "elm,action,pop";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "hide_start2";
+           }
+           program { name: "hide_start";
+               signal: "elm,action,hide";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "clip";
+               target: "clip_base";
+               after: "hide_start2";
+           }
+           program { name: "hide_start2";
+               action:  STATE_SET "hidden" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+               target: "clip_base";
+               after: "hide_end";
+           }
+           program { name: "hide_end";
+               action: SIGNAL_EMIT "elm,action,hide,finished" "";
+           }
+           program { name: "reset";
+               signal: "elm,action,reset";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "clip_base";
+               target: "clip";
+           }
+       }
+   }
+   group { name: "elm/pager/base/fade_invisible";
+       data.item: "onshow" "raise";
+       // other options
+       //      data.item: "onhide" "lower";
+       //      data.item: "onshow" "lower";
+       parts {
+           part { name: "clip";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1 {
+                       offset: -9999 -9999;
+                   }
+                   rel2 {
+                       offset: 9999 9999;
+                   }
+                   color: 255 255 255 255;
+               }
+               description { state: "visible" 0.0;
+                   inherit: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 0;
+                   visible: 0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   rel1 {
+                       offset: 8 8;
+                   }
+                   rel2 {
+                       offset: -9 -9;
+                   }
+               }
+           }
+       }
+       programs {
+           program { name: "push_start";
+               signal: "elm,action,push";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "clip";
+               after: "show_start2";
+           }
+           program { name: "show_start";
+               signal: "elm,action,show";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "clip";
+               after: "show_start2";
+           }
+           program { name: "show_start2";
+               action:  STATE_SET "visible" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+               after: "show_end";
+           }
+           program { name: "show_end";
+               action: SIGNAL_EMIT "elm,action,show,finished" "";
+           }
+           program { name: "pop_start";
+               signal: "elm,action,pop";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "clip";
+               after: "hide_start2";
+           }
+           program { name: "hide_start";
+               signal: "elm,action,hide";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "clip";
+               after: "hide_start2";
+           }
+           program { name: "hide_start2";
+               action:  STATE_SET "hidden" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+               after: "hide_end";
+           }
+           program { name: "hide_end";
+               action: SIGNAL_EMIT "elm,action,hide,finished" "";
+           }
+           program { name: "reset";
+               signal: "elm,action,reset";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "clip";
+           }
+       }
+   }
+
+   group { name: "elm/pager/base/flip";
+      data.item: "onshow" "raise";
+      images {
+         image: "frame_1.png" COMP;
+         image: "frame_2.png" COMP;
+         image: "dia_grad.png" COMP;
+      }
+      parts {
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               map {
+                  on: 1;
+                  smooth: 1;
+                  backface_cull: 1;
+                  perspective_on: 1;
+               }
+               perspective {
+                  zplane: 0;
+                  focal: 1000;
+               }
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               map.rotation.y: 90.0;
+            }
+            description { state: "before_hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               map.rotation.y: -90.0;
+            }
+         }
+      }
+      programs {
+         program { name: "push_start";
+            signal: "elm,action,push";
+            source: "elm";
+            after: "push1";
+         }
+         program { name: "push1";
+            action:  STATE_SET "hidden" 0.0;
+            target: "elm.swallow.content";
+            after: "push2";
+         }
+         program { name: "push2";
+            action:  STATE_SET "default" 0.0;
+            in: 0.5 0.0;
+            transition: LINEAR 0.5;
+            target: "elm.swallow.content";
+            after: "push3";
+         }
+         program { name: "push3";
+            action: SIGNAL_EMIT "elm,action,show,finished" "";
+         }
+
+         program { name: "show_start";
+            signal: "elm,action,show";
+            source: "elm";
+            after: "show1";
+         }
+         program { name: "show1";
+            action:  STATE_SET "before_hidden" 0.0;
+            target: "elm.swallow.content";
+            after: "show2";
+         }
+         program { name: "show2";
+            action:  STATE_SET "default" 0.0;
+            in: 0.5 0.0;
+            transition: LINEAR 0.5;
+            target: "elm.swallow.content";
+            after: "show3";
+         }
+         program { name: "show3";
+            action: SIGNAL_EMIT "elm,action,show,finished" "";
+         }
+
+         program { name: "pop_start";
+            signal: "elm,action,pop";
+            source: "elm";
+            after: "pop1";
+         }
+         program { name: "pop1";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.swallow.content";
+            after: "pop2";
+         }
+         program { name: "pop2";
+            action:  STATE_SET "hidden" 0.0;
+            transition: LINEAR 0.5;
+            target: "elm.swallow.content";
+            after: "pop3";
+         }
+         program { name: "pop3";
+            action: SIGNAL_EMIT "elm,action,hide,finished" "";
+         }
+
+         program { name: "hide_start";
+            signal: "elm,action,hide";
+            source: "elm";
+            after: "hide1";
+         }
+         program { name: "hide1";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.swallow.content";
+            after: "hide2";
+         }
+         program { name: "hide2";
+            action:  STATE_SET "before_hidden" 0.0;
+            transition: LINEAR 0.5;
+            target: "elm.swallow.content";
+            after: "hide3";
+         }
+         program { name: "hide3";
+            action: SIGNAL_EMIT "elm,action,hide,finished" "";
+         }
+
+         program { name: "reset";
+            signal: "elm,action,reset";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.swallow.content";
+         }
+      }
+   }
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// FIXME: this doesn't look too hot. need to fix it up
+   group { name: "elm/progressbar/horizontal/default";
+      images {
+         image: "shelf_inset.png" COMP;
+         image: "bt_sm_base2.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+      }
+      parts {
+         part { name: "elm.background.progressbar";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+               }
+            }
+         }
+         part { name: "elm.swallow.bar";
+            mouse_events: 0;
+            type: SWALLOW;
+            description {
+               min: 48 28;
+               max: 99999 28;
+               state: "default" 0.0;
+               rel1 {
+                  to_x: "elm.text";
+                  to_y: "elm.background.progressbar";
+                  relative: 1.0 0.0;
+               }
+               rel2 {
+                  to: "elm.background.progressbar";
+                  relative: 1.0 1.0;
+               }
+            }
+         }
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 0;
+               align: 0.0 0.5;
+               rel1 {
+                  offset: 4 0;
+                  to_y: "elm.background.progressbar";
+               }
+               rel2 {
+                  offset: 3 -1;
+                  relative: 0.0 1.0;
+                  to_y: "elm.background.progressbar";
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               aspect: 1.0 1.0;
+               aspect_preference: VERTICAL;
+               rel2.offset: 4 -1;
+            }
+         }
+         part { name: "elm.text";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               visible: 0;
+               fixed: 1 1;
+               align: 0.0 0.5;
+               rel1.to_x: "elm.swallow.content";
+               rel1.relative: 1.0 0.0;
+               rel1.offset: -1 4;
+               rel2.to_x: "elm.swallow.content";
+               rel2.relative: 1.0 1.0;
+               rel2.offset: -1 -5;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  min: 0 0;
+                  align: 0.0 0.5;
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               text.min: 1 1;
+               rel1.offset: 0 4;
+               rel2.offset: 0 -5;
+            }
+         }
+
+         part { name: "background";
+            mouse_events: 0;
+            clip_to: "elm.background.progressbar";
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.0 0.0;
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 1.0 1.0;
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "shelf_inset.png";
+                  border: 7 7 7 7;
+               }
+            }
+         }
+
+         part { name: "elm.text.status";
+            type: TEXT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               visible: 1;
+               rel1 {
+                  to: "background";
+                  relative: 0.5 0.5;
+               }
+               rel2 {
+                  to: "background";
+                  relative: 0.5 0.5;
+               }
+               text {
+                  font: "Sans:style=Bold,Edje-Vera-Bold";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.5 0.0;
+               }
+               color: 0 0 0 255;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               text.min: 0 0;
+            }
+         }
+
+         part { name: "elm.progress.progressbar";
+            mouse_events: 0;
+            clip_to: "elm.background.progressbar";
+            description {
+               state: "default" 0.0;
+               min: 14 28;
+               fixed: 1 1;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.0 0.0;
+               }
+               rel2 {
+                  to_y: "elm.swallow.bar";
+                  to_x: "elm.cur.progressbar";
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "bt_sm_base2.png";
+                  border: 6 6 6 6;
+               }
+            }
+            description {
+               state: "invert" 0.0;
+               inherit: "default" 0.0;
+               rel1 {
+                  to_y: "elm.swallow.bar";
+                  to_x: "elm.cur.progressbar";
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 1.0 1.0;
+               }
+            }
+            description {
+               state: "state_begin" 0.0;
+               inherit: "default" 0.0;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.0 0.0;
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 0.1 1.0;
+               }
+            }
+            description {
+               state: "state_end" 0.0;
+               inherit: "default" 0.0;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.9 0.0;
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 1.0 1.0;
+               }
+            }
+         }
+         part { name: "text-bar";
+            type: TEXT;
+            mouse_events: 0;
+            clip_to: "progress-rect";
+            effect: SOFT_SHADOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               fixed: 1 1;
+               visible: 1;
+               rel1.to: "elm.text.status";
+               rel1.offset: -1 -1;
+               rel2.to: "elm.text.status";
+               text {
+                  text_source: "elm.text.status";
+                  font: "Sans:style=Bold,Edje-Vera-Bold";
+                  size: 10;
+                  min: 1 1;
+                  align: 0.0 0.0;
+               }
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               text.min: 0 0;
+            }
+         }
+
+         part { name: "over1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.progress.progressbar";
+               rel2.to: "elm.progress.progressbar";
+               rel2.relative: 1.0 0.5;
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+
+         part { name: "over2";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               rel1.to: "elm.progress.progressbar";
+               rel2.to: "elm.progress.progressbar";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+
+         part { name: "elm.cur.progressbar";
+            mouse_events: 0;
+            dragable {
+               confine: "background";
+               x: 1 1 1;
+               y: 0 0 0;
+            }
+            description { state: "default" 0.0;
+               min: 14 28;
+               fixed: 1 1;
+               visible: 0;
+               rel1 {
+                  to: "background";
+                  relative: 0 0;
+               }
+               rel2.to: "background";
+           }
+         }
+         part { name: "progress-rect";
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               rel1.to: "elm.progress.progressbar";
+               rel2.to: "elm.progress.progressbar";
+            }
+         }
+      }
+      programs {
+         program { name: "label_show";
+            signal: "elm,state,text,visible";
+            source: "elm";
+            action:  STATE_SET "visible" 0.0;
+            target: "elm.text";
+         }
+         program { name: "label_hide";
+            signal: "elm,state,text,hidden";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+         program { name: "icon_show";
+            signal: "elm,state,icon,visible";
+            source: "elm";
+            action:  STATE_SET "visible" 0.0;
+            target: "elm.swallow.content";
+         }
+         program { name: "icon_hide";
+            signal: "elm,state,icon,hidden";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.swallow.content";
+         }
+         program { name: "units_show";
+            signal: "elm,state,units,visible";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "text-bar";
+            target: "elm.text.status";
+         }
+         program { name: "units_hide";
+            signal: "elm,state,units,hidden";
+            source: "elm";
+            action:  STATE_SET "hidden" 0.0;
+            target: "text-bar";
+            target: "elm.text.status";
+         }
+         program { name: "slide_to_end";
+            action:  STATE_SET "state_end" 0.0;
+            transition: LINEAR 0.5;
+            target: "elm.progress.progressbar";
+            after: "slide_to_begin";
+         }
+         program { name: "slide_to_begin";
+            signal: "elm,state,slide,begin";
+            action: STATE_SET "state_begin" 0.0;
+            target: "elm.progress.progressbar";
+            transition: LINEAR 0.5;
+            after: "slide_to_end";
+         }
+         program { name: "start_pulse";
+            signal: "elm,state,pulse,start";
+            source: "elm";
+            after: "slide_to_end";
+         }
+         program { name: "stop_pulse";
+            signal: "elm,state,pulse,stop";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "slide_to_begin";
+            target: "slide_to_end";
+            target: "start_pulse";
+            after: "state_pulse";
+         }
+         program { name: "state_pulse";
+            signal: "elm,state,pulse";
+            source: "elm";
+            action: STATE_SET "state_begin" 0.0;
+            target: "elm.progress.progressbar";
+            after: "units_hide";
+         }
+         program { name: "state_fraction";
+            signal: "elm,state,fraction";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "slide_to_begin";
+            target: "slide_to_end";
+            target: "start_pulse";
+            action: STATE_SET "default" 0.0;
+            target: "elm.progress.progressbar";
+         }
+         program { name: "set_invert_on";
+            signal: "elm,state,inverted,on";
+            source: "elm";
+            action:  STATE_SET "invert" 0.0;
+            target: "elm.progress.progressbar";
+         }
+         program { name: "set_invert_off";
+            signal: "elm,state,inverted,off";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.progress.progressbar";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/progressbar/vertical/default";
+      images {
+         image: "shelf_inset.png" COMP;
+         image: "bt_sm_base2.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+      }
+      parts {
+         part { name: "elm.background.progressbar";
+            type: RECT;
+            mouse_events: 0;
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.bar";
+            type: SWALLOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               min: 28 48;
+               max: 28 9999;
+               align: 0.5 1.0;
+               rel1 {
+                  to_y: "elm.text";
+                  relative: 0.0 1.0;
+                  offset: 0 2;
+               }
+               rel2 {
+                  to_y: "elm.text.box";
+                  relative: 1.0 0.0;
+                  offset: -1 -3;
+               }
+            }
+         }
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 0;
+               align: 0.5 0.0;
+               rel1 {
+                  offset: 0 4;
+                  to_x: "elm.swallow.bar";
+               }
+               rel2 {
+                  offset: -1 3;
+                  relative: 1.0 0.0;
+                  to_x: "elm.swallow.bar";
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               aspect: 1.0 1.0;
+               aspect_preference: HORIZONTAL;
+               rel2.offset: -1 4;
+            }
+         }
+         part { name: "elm.text";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               visible: 0;
+               fixed: 1 1;
+               align: 0.5 0.0;
+               rel1.to_y: "elm.swallow.content";
+               rel1.relative: 0.5 1.0;
+               rel1.offset: 0 -1;
+               rel2.to_y: "elm.swallow.content";
+               rel2.relative: 0.5 1.0;
+               rel2.offset: -1 -1;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 10;
+                  min: 0 0;
+                  align: 0.5 0.0;
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               text.min: 1 1;
+               rel1.offset: 4 0;
+               rel2.offset: -5 0;
+            }
+         }
+
+         part { name: "background";
+            mouse_events: 0;
+            clip_to: "elm.background.progressbar";
+            description {
+               state: "default" 0.0;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.0 0.0;
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 1.0 1.0;
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "shelf_inset.png";
+                  border: 7 7 7 7;
+               }
+            }
+         }
+
+         part { name: "elm.progress.progressbar";
+            mouse_events: 0;
+            clip_to: "elm.background.progressbar";
+            description {
+               state: "default" 0.0;
+               min: 28 14;
+               fixed: 1 1;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.0 0.0;
+               }
+               rel2 {
+                  to_x: "elm.swallow.bar";
+                  to_y: "elm.cur.progressbar";
+                  offset: -1 -1;
+               }
+               image {
+                  normal: "bt_sm_base2.png";
+                  border: 6 6 6 6;
+               }
+            }
+            description {
+               state: "invert" 0.0;
+               inherit: "default" 0.0;
+               rel1 {
+                  to_x: "elm.swallow.bar";
+                  to_y: "elm.cur.progressbar";
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 1.0 1.0;
+               }
+            }
+            description {
+               state: "state_begin" 0.0;
+               inherit: "default" 0.0;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.0 0.0;
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 1.0 0.1;
+               }
+            }
+            description {
+               state: "state_end" 0.0;
+               inherit: "default" 0.0;
+               rel1 {
+                  to: "elm.swallow.bar";
+                  relative: 0.0 0.9;
+               }
+               rel2 {
+                  to: "elm.swallow.bar";
+                  relative: 1.0 1.0;
+               }
+            }
+         }
+
+         part { name: "over1";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.progress.progressbar";
+               rel2.to: "elm.progress.progressbar";
+               rel2.relative: 1.0 0.5;
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+
+         part { name: "over2";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               rel1.to: "elm.progress.progressbar";
+               rel2.to: "elm.progress.progressbar";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+         }
+
+         part { name: "elm.cur.progressbar";
+            mouse_events: 0;
+            dragable {
+               confine: "background";
+               x: 0 0 0;
+               y: 1 1 1;
+            }
+            description { state: "default" 0.0;
+               min: 28 14;
+               fixed: 1 1;
+               visible: 0;
+               rel1 {
+                  to: "background";
+                  relative: 0 0;
+               }
+               rel2.to: "background";
+           }
+         }
+
+         part { name: "elm.text.box";
+            mouse_events: 0;
+            type: RECT;
+            description { state: "default" 0.0;
+               visible: 0;
+               rel1 {
+                  to: "elm.text.status";
+                  offset: -2 -2;
+               }
+               rel2 {
+                  to: "elm.text.status";
+                  offset: 2 2;
+               }
+               color: 255 255 255 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+         }
+         part { name: "elm.text.status";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               visible: 0;
+               fixed: 1 1;
+               align: 0.5 1.0;
+               rel1.relative: 0.0 1.0;
+               rel1.offset: 2 0;
+               rel2.relative: 1.0 1.0;
+               rel2.offset: -2 0;
+               color: 0 0 0 255;
+               text {
+                  font: "Sans:style=Bold,Edje-Vera-Bold";
+                  size: 10;
+                  min: 0 0;
+                  align: 0.5 0.0;
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               fixed: 1 1;
+               visible: 1;
+               text.min: 1 1;
+               rel1.offset: 8 -9;
+               rel2.offset: -9 -9;
+            }
+         }
+      }
+      programs {
+         program { name: "label_show";
+            signal: "elm,state,text,visible";
+            source: "elm";
+            action:  STATE_SET "visible" 0.0;
+            target: "elm.text";
+         }
+         program { name: "label_hide";
+            signal: "elm,state,text,hidden";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.text";
+         }
+         program { name: "icon_show";
+            signal: "elm,state,icon,visible";
+            source: "elm";
+            action:  STATE_SET "visible" 0.0;
+            target: "elm.swallow.content";
+         }
+         program { name: "icon_hide";
+            signal: "elm,state,icon,hidden";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.swallow.content";
+         }
+         program { name: "units_show";
+            signal: "elm,state,units,visible";
+            source: "elm";
+            action:  STATE_SET "visible" 0.0;
+            target: "elm.text.status";
+            target: "elm.text.box";
+         }
+         program { name: "units_hide";
+            signal: "elm,state,units,hidden";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.text.status";
+            target: "elm.text.box";
+         }
+         program { name: "slide_to_end";
+            action:  STATE_SET "state_end" 0.0;
+            transition: LINEAR 0.5;
+            target: "elm.progress.progressbar";
+            after: "slide_to_begin";
+         }
+         program { name: "slide_to_begin";
+            action:  STATE_SET "state_begin" 0.0;
+            target: "elm.progress.progressbar";
+            transition: LINEAR 0.5;
+            after: "slide_to_end";
+         }
+         program { name: "start_pulse";
+            signal: "elm,state,pulse,start";
+            source: "elm";
+            action: STATE_SET "state_begin" 0.0;
+            target: "elm.progress.progressbar";
+            after: "slide_to_end";
+         }
+         program { name: "stop_pulse";
+            signal: "elm,state,pulse,stop";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "slide_to_begin";
+            target: "slide_to_end";
+            target: "start_pulse";
+            after: "state_pulse";
+         }
+         program { name: "state_pulse";
+            signal: "elm,state,pulse";
+            source: "elm";
+            action: STATE_SET "state_begin" 0.0;
+            target: "elm.progress.progressbar";
+            after: "units_hide";
+         }
+         program { name: "state_fraction";
+            signal: "elm,state,fraction";
+            source: "elm";
+            action: ACTION_STOP;
+            target: "slide_to_begin";
+            target: "slide_to_end";
+            target: "start_pulse";
+            action: STATE_SET "default" 0.0;
+            target: "elm.progress.progressbar";
+         }
+         program { name: "set_invert_on";
+            signal: "elm,state,inverted,on";
+            source: "elm";
+            action:  STATE_SET "invert" 0.0;
+            target: "elm.progress.progressbar";
+            target: "elm.cur.progressbar";
+         }
+         program { name: "set_invert_off";
+            signal: "elm,state,inverted,off";
+            source: "elm";
+            action:  STATE_SET "default" 0.0;
+            target: "elm.progress.progressbar";
+            target: "elm.cur.progressbar";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/separator/horizontal/default";
+       images {
+           image: "separator_h.png" COMP;
+       }
+       parts {
+           part { name: "separator"; // separator group
+               description { state: "default" 0.0;
+                   min: 2 2;
+                   rel1.offset: 4 4;
+                   rel2.offset: -5 -5;
+                   image {
+                       normal: "separator_h.png";
+                   }
+                   fill {
+                       smooth: 0;
+                   }
+               }
+           }
+       }
+   }
+
+   ///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/separator/vertical/default";
+       images {
+           image: "separator_v.png" COMP;
+       }
+       parts {
+           part { name: "separator"; // separator group
+               description { state: "default" 0.0;
+                   min: 2 2;
+                   rel1.offset: 4 4;
+                   rel2.offset: -5 -5;
+                   image {
+                       normal: "separator_v.png";
+                   }
+                   fill {
+                       smooth: 0;
+                   }
+               }
+           }
+       }
+   }
+
+   group { name: "elm/progressbar/horizontal/wheel";
+       images {
+           image: "busy-1.png" COMP;
+           image: "busy-2.png" COMP;
+           image: "busy-3.png" COMP;
+           image: "busy-4.png" COMP;
+           image: "busy-5.png" COMP;
+           image: "busy-6.png" COMP;
+           image: "busy-7.png" COMP;
+           image: "busy-8.png" COMP;
+           image: "busy-9.png" COMP;
+       }
+       parts {
+           part { name: "elm.background.progressbar";
+               mouse_events: 0;
+               type: RECT;
+               description {
+                   state: "default" 0.0;
+               }
+           }
+           part { name: "elm.swallow.bar";
+               mouse_events: 0;
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   min: 0 0;
+                   max: 0 0;
+                   visible: 0;
+               }
+           }
+           part { name: "elm.swallow.content";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   min: 0 0;
+                   max: 0 0;
+                   visible: 0;
+               }
+           }
+           part { name: "background";
+               mouse_events: 0;
+               clip_to: "elm.background.progressbar";
+               description {
+                   state: "default" 0.0;
+                   min: 32 32;
+                   max: 32 32;
+                   visible: 1;
+                   aspect: 1.0 1.0;
+                   aspect_preference: BOTH;
+                   image {
+                       normal: "busy-9.png";
+                       border: 7 7 7 7;
+                   }
+               }
+               description {
+                   state: "pulse" 0.0;
+                   inherit: "default" 0.0;
+                   image {
+                       normal: "busy-9.png";
+                       tween:  "busy-1.png";
+                       tween:  "busy-2.png";
+                       tween:  "busy-3.png";
+                       tween:  "busy-4.png";
+                       tween:  "busy-5.png";
+                       tween:  "busy-6.png";
+                       tween:  "busy-7.png";
+                       tween:  "busy-8.png";
+                       border: 7 7 7 7;
+                   }
+               }
+           }
+       }
+       programs {
+           program { name: "start_pulse";
+               signal: "elm,state,pulse,start";
+               source: "elm";
+               action: STATE_SET "pulse" 0.0;
+               target: "background";
+               transition: LINEAR 0.5;
+               after: "start_pulse";
+           }
+           program { name: "stop_pulse";
+               signal: "elm,state,pulse,stop";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "background";
+           }
+       }
+   }
+
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/spinner/base/default";
+       images {
+           image: "shelf_inset.png" COMP;
+           image: "bt_base1.png" COMP;
+           image: "bt_hilight.png" COMP;
+           image: "bt_shine.png" COMP;
+           image: "bt_glow.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+           image: "sp_bt_l.png" COMP;
+           image: "sp_bt_r.png" COMP;
+       }
+       parts {
+           part { name: "bg";
+               type: RECT;
+               description { state: "default" 0.0;
+                   min: 0 30;
+                   rel1.offset: 1 1;
+                   rel2.offset: -2 -2;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "conf_over";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   image {
+                       normal: "shelf_inset.png";
+                       border: 7 7 7 7;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "left_bt";
+               mouse_events:  1;
+               description { state: "default" 0.0;
+                   rel1 { to: "bg";
+                       offset: 3 3;
+                   }
+                   rel2 { to: "bg";
+                       offset: -4 -4;
+                   }
+                   align: 0.0 0.5;
+                   min: 24 24;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   image {
+                       normal: "bt_base1.png";
+                       border: 6 6 6 6;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "bt_base1.png";
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+               }
+           }
+           part {        name: "left_over1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "left_bt";
+                   rel2 { to: "left_bt";
+                       relative: 1.0 0.5;
+                   }
+                   image {
+                       normal: "bt_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "left_over2";
+               mouse_events: 1;
+               repeat_events: 1;
+               ignore_flags: ON_HOLD;
+               description { state: "default" 0.0;
+                   rel1.to: "left_bt";
+                   rel2.to: "left_bt";
+                   image {
+                       normal: "bt_shine.png";
+                       border: 7 7 7 7;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 0;
+               }
+           }
+           part { name: "left_over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "left_bt";
+                   rel2.to: "left_bt";
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "right_bt";
+               mouse_events:  1;
+               description { state: "default" 0.0;
+                   rel1 { to: "bg";
+                       offset: -26 3;
+                   }
+                   rel2 { to: "bg";
+                       offset: -4 -4;
+                   }
+                   align: 1.0 0.5;
+                   min: 24 24;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   image {
+                       normal: "bt_base1.png";
+                       border: 5 5 4 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "bt_base1.png";
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+               }
+           }
+           part { name: "right_over1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "right_bt";
+                   rel2 { to: "right_bt";
+                       relative: 1.0 0.5;
+                   }
+                   image {
+                       normal: "bt_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "right_over2";
+               mouse_events: 1;
+               repeat_events: 1;
+               ignore_flags: ON_HOLD;
+               description { state: "default" 0.0;
+                   rel1.to: "right_bt";
+                   rel2.to: "right_bt";
+                   image {
+                       normal: "bt_shine.png";
+                       border: 7 7 7 7;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 0;
+               }
+           }
+           part { name: "right_over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "right_bt";
+                   rel2.to: "right_bt";
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "left_bt_icon";
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "left_bt";
+                   rel1.offset: 4 4;
+                   rel2.to: "left_bt";
+                   rel2.offset: -5 -5;
+                   align: 0.5 0.5;
+                   min: 16 16;
+                   aspect: 1.0 1.0;
+                   aspect_preference: BOTH;
+                   image.normal: "sp_bt_l.png";
+               }
+           }
+           part { name: "right_bt_icon";
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "right_bt";
+                   rel1.offset: 4 4;
+                   rel2.to: "right_bt";
+                   rel2.offset: -5 -5;
+                   align: 0.5 0.5;
+                   min: 16 16;
+                   aspect: 1.0 1.0;
+                   aspect_preference: BOTH;
+                   image.normal: "sp_bt_r.png";
+               }
+           }
+           part { name: "elm.text";
+               type: TEXT;
+               mouse_events: 0;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 1;
+                   align: 0.0 0.5;
+                   rel1 { relative: 1.0 0.0;
+                       offset: 3 2;
+                       to_x: "left_bt";
+                       to_y: "bg";
+                   }
+                   rel2 { relative: 0.0 1.0;
+                       offset: -3 -2;
+                       to_x: "right_bt";
+                       to_y: "bg";
+                   }
+                   color: 0 0 0 255;
+                   text {
+                       font: "Sans,Edje-Vera";
+                       size: 10;
+                       min: 1 1;
+                       align: 0.5 0.5;
+                   }
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+               description { state: "disabled_active" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+           }
+           part { name: "elm.dragable.slider";
+               type: RECT;
+               mouse_events: 0;
+               scale: 1;
+               dragable {
+                   x: 1 1 0;
+                   y: 0 0 0;
+               }
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   fixed: 1 1;
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "button_events";
+               type: RECT;
+               dragable {
+                   events: "elm.dragable.slider";
+               }
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.text";
+                   rel2.to: "elm.text";
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "elm.swallow.entry";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   align: 0.5 0.5;
+                   rel1 { relative: 1.0 0.5;
+                       offset: 3 2;
+                       to_x: "left_bt";
+                       to_y: "bg";
+                   }
+                   rel2 { relative: 0.0 0.5;
+                       offset: -3 -2;
+                       to_x: "right_bt";
+                       to_y: "bg";
+                   }
+                   fixed: 1 1;
+                   color: 0 0 0 0;
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+               description { state: "disabled_active" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+           }
+           part { name: "disabler";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+           }
+       }
+       programs {
+           program { name: "text_show";
+               signal: "elm,state,text,visible";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "elm.text";
+           }
+           program { name: "text_hide";
+               signal: "elm,state,text,hidden";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "elm.text";
+           }
+           program { name: "dec";
+               signal: "mouse,down,1";
+               source: "left_bt";
+               action: SIGNAL_EMIT "elm,action,decrement,start" "";
+           }
+           program { name: "dec2";
+               signal: "mouse,up,1";
+               source: "left_bt";
+               action: SIGNAL_EMIT "elm,action,decrement,stop" "";
+           }
+           program { name: "inc";
+               signal: "mouse,down,1";
+               source: "right_bt";
+               action: SIGNAL_EMIT "elm,action,increment,start" "";
+           }
+           program { name: "inc2";
+               signal: "mouse,up,1";
+               source: "right_bt";
+               action: SIGNAL_EMIT "elm,action,increment,stop" "";
+           }
+           program {
+               name:   "left_bt_click";
+               signal: "mouse,down,1";
+               source: "left_over2";
+               action: STATE_SET "clicked" 0.0;
+               target: "left_bt";
+           }
+           program {
+               name:   "left_bt_unclick";
+               signal: "mouse,up,1";
+               source: "left_over2";
+               action: STATE_SET "default" 0.0;
+               target: "left_bt";
+           }
+           program {
+               name:   "left_bt_click2";
+               signal: "mouse,down,1";
+               source: "left_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "left_over3";
+           }
+           program {
+               name:   "left_bt_unclick2";
+               signal: "mouse,up,1";
+               source: "left_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "left_over3";
+           }
+           program {
+               name:   "left_bt_unclick3";
+               signal: "mouse,up,1";
+               source: "left_over2";
+               action: SIGNAL_EMIT "elm,action,click" "";
+           }
+           program {
+               name:   "left_bt_pressed_anim";
+               signal: "elm,left,anim,activate";
+               source: "elm";
+               action: STATE_SET "clicked" 0.0;
+               target: "left_bt";
+               target: "left_over3";
+               after: "left_bt_unpressed_anim";
+           }
+           program {
+               name:   "left_bt_unpressed_anim";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "left_bt";
+               target: "left_over3";
+           }
+
+           program {
+               name:   "right_bt_click";
+               signal: "mouse,down,1";
+               source: "right_over2";
+               action: STATE_SET "clicked" 0.0;
+               target: "right_bt";
+           }
+           program {
+               name:   "right_bt_unclick";
+               signal: "mouse,up,1";
+               source: "right_over2";
+               action: STATE_SET "default" 0.0;
+               target: "right_bt";
+           }
+           program {
+               name:   "right_bt_click2";
+               signal: "mouse,down,1";
+               source: "right_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "right_over3";
+           }
+           program {
+               name:   "right_bt_unclick2";
+               signal: "mouse,up,1";
+               source: "right_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "right_over3";
+           }
+           program {
+               name:   "right_bt_unclick3";
+               signal: "mouse,up,1";
+               source: "right_over2";
+               action: SIGNAL_EMIT "elm,action,click" "";
+           }
+           program {
+               name:   "right_bt_pressed_anim";
+               signal: "elm,right,anim,activate";
+               source: "elm";
+               action: STATE_SET "clicked" 0.0;
+               target: "right_bt";
+               target: "right_over3";
+               after: "right_bt_unpressed_anim";
+           }
+           program {
+               name:   "right_bt_unpressed_anim";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "right_bt";
+               target: "right_over3";
+           }
+
+           program { name: "disable";
+               signal: "elm,state,disabled";
+               source: "elm";
+               action: STATE_SET "disabled" 0.0;
+               target: "left_bt";
+               target: "left_over1";
+               target: "left_over2";
+               target: "right_bt";
+               target: "right_over1";
+               target: "right_over2";
+               target: "disabler";
+               after: "disable_text";
+           }
+           program { name: "disable_text";
+               script {
+                   new st[31];
+                   new Float:vl;
+                   get_state(PART:"elm.text", st, 30, vl);
+                   if (!strcmp(st, "active"))
+                   set_state(PART:"elm.text", "disabled_active", 0.0);
+                   else
+                   set_state(PART:"elm.text", "disabled", 0.0);
+
+                   get_state(PART:"elm.swallow.entry", st, 30, vl);
+                   if (!strcmp(st, "active"))
+                   set_state(PART:"elm.swallow.entry", "disabled_active", 0.0);
+                   else
+                   set_state(PART:"elm.swallow.entry", "disabled", 0.0);
+               }
+           }
+           program { name: "enable";
+               signal: "elm,state,enabled";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "left_bt";
+               target: "left_over1";
+               target: "left_over2";
+               target: "right_bt";
+               target: "right_over1";
+               target: "right_over2";
+               target: "disabler";
+               after: "enable_text";
+           }
+           program { name: "enable_text";
+               script {
+                   new st[31];
+                   new Float:vl;
+                   get_state(PART:"elm.text", st, 30, vl);
+                   if (!strcmp(st, "disabled_active"))
+                   set_state(PART:"elm.text", "active", 0.0);
+                   else
+                   set_state(PART:"elm.text", "default", 0.0);
+
+                   get_state(PART:"elm.swallow.entry", st, 30, vl);
+                   if (!strcmp(st, "disabled_active"))
+                   set_state(PART:"elm.swallow.entry", "active", 0.0);
+                   else
+                   set_state(PART:"elm.swallow.entry", "default", 0.0);
+               }
+           }
+           program { name: "active";
+               signal: "elm,state,active";
+               source: "elm";
+               action: STATE_SET "active" 0.0;
+               target: "elm.text";
+               target: "elm.swallow.entry";
+           }
+           program { name: "inactive";
+               signal: "elm,state,inactive";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "elm.text";
+               target: "elm.swallow.entry";
+           }
+           program { name: "toggle_text";
+               signal: "mouse,up,1";
+               source: "button_events";
+               action: SIGNAL_EMIT "elm,action,entry,toggle" "";
+           }
+       }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/spinner/base/vertical";
+       images {
+           image: "shelf_inset.png" COMP;
+           image: "bt_hilight.png" COMP;
+           image: "bt_shine.png" COMP;
+           image: "bt_glow.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+           image: "up.png" COMP;
+           image: "down.png" COMP;
+           image: "bt_spinner_up.png" COMP;
+           image: "bt_spinner_down.png" COMP;
+           image: "bt_spinner_hilight.png" COMP;
+       }
+       parts {
+           part { name: "bg";
+               type: RECT;
+               description { state: "default" 0.0;
+                   min: 0 30;
+                   rel1.offset: 1 1;
+                   rel2.offset: -2 -2;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "conf_over";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   rel1 {
+                     to: "bg";
+                     relative: 0.0 0.0;
+                   }
+                   rel2 {
+                      to: "bg";
+                   }
+                   image {
+                       normal: "shelf_inset.png";
+                       border: 7 7 7 7;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "down_bt";
+               mouse_events:  1;
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   rel1 {
+                       to: "up_bt";
+                       relative: 0 1;
+                       offset: 0 1;
+                   }
+                   rel2 {
+                       to_y: "bg";
+                       to_x: "up_bt";
+                       relative: 1 1;
+                       offset: -1 -4;
+                   }
+                   align: 1.0 0.5;
+                   min: 24 16;
+                   image {
+                       normal: "bt_spinner_down.png";
+                       border: 6 6 6 6;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "bt_spinner_down.png";
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+               }
+           }
+           part { name: "down_over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "down_bt";
+                   rel2.to: "down_bt";
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "up_bt";
+               mouse_events:  1;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   rel1 { to: "bg";
+                       relative: 0 0;
+                       offset: 0 2;
+                   }
+                   rel2 { to: "bg";
+                       relative: 1 0.5;
+                       offset: -3 0;
+                   }
+                   align: 1.0 0.5;
+                   min: 24 16;
+                   aspect: 1.5 1.0;
+                   aspect_preference: BOTH;
+                   image {
+                       normal: "bt_spinner_up.png";
+                       border: 6 6 6 6;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "bt_spinner_up.png";
+                   image.middle: SOLID;
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   image {
+                       normal: "bt_dis_base.png";
+                       border: 4 4 4 4;
+                   }
+               }
+           }
+           part { name: "up_over1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "up_bt";
+                   rel2 { to: "up_bt";
+                       relative: 1.0 0.5;
+                   }
+                   image {
+                       normal: "bt_spinner_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+               description { state: "disabled" 0.0;
+                   inherit:  "default" 0.0;
+                   image {
+                       normal: "bt_dis_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "up_over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "up_bt";
+                   rel2.to: "up_bt";
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "down_bt_icon";
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "down_bt";
+                   rel1.offset: 5 3;
+                   rel2.to: "down_bt";
+                   rel2.offset: -6 -3;
+                   align: 0.5 0.5;
+                   image.normal: "down.png";
+               }
+           }
+           part { name: "up_bt_icon";
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "up_bt";
+                   rel1.offset: 5 3;
+                   rel2.to: "up_bt";
+                   rel2.offset: -6 -3;
+                   align: 0.5 0.5;
+                   image.normal: "up.png";
+               }
+           }
+           part { name: "elm.text";
+               type: TEXT;
+               mouse_events: 0;
+               scale: 1;
+               description { state: "default" 0.0;
+                   visible: 1;
+                   align: 0.0 0.5;
+                   rel1 { relative: 0.0 0.0;
+                       offset: 3 2;
+                       to_x: "bg";
+                       to_y: "bg";
+                   }
+                   rel2 { relative: 0.0 1.0;
+                       offset: -3 -2;
+                       to_x: "down_bt";
+                       to_y: "bg";
+                   }
+                   color: 0 0 0 255;
+                   text {
+                       font: "Sans,Edje-Vera";
+                       size: 10;
+                       min: 1 1;
+                       align: 0.5 0.5;
+                   }
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+               description { state: "disabled_active" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 128;
+                   color3: 0 0 0 0;
+               }
+           }
+           part { name: "elm.dragable.slider";
+               type: RECT;
+               mouse_events: 0;
+               scale: 1;
+               dragable {
+                   x: 1 1 0;
+                   y: 0 0 0;
+               }
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   fixed: 1 1;
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "button_events";
+               type: RECT;
+               dragable {
+                   events: "elm.dragable.slider";
+               }
+               mouse_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.text";
+                   rel2.to: "elm.text";
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "elm.swallow.entry";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   align: 0.5 0.5;
+                   rel1 { relative: 0.0 0.5;
+                       offset: 3 2;
+                       to: "bg";
+                   }
+                   rel2 { relative: 1.0 0.5;
+                       offset: -3 -2;
+                       to: "bg";
+                   }
+                   fixed: 1 1;
+                   color: 0 0 0 0;
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+               description { state: "disabled_active" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 0;
+               }
+           }
+           part { name: "disabler";
+               type: RECT;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+                   visible: 0;
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+               }
+           }
+       }
+       programs {
+           program { name: "text_show";
+               signal: "elm,state,text,visible";
+               source: "elm";
+               action:  STATE_SET "visible" 0.0;
+               target: "elm.text";
+           }
+           program { name: "text_hide";
+               signal: "elm,state,text,hidden";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "elm.text";
+           }
+           program { name: "dec";
+               signal: "mouse,down,1";
+               source: "down_bt";
+               action: SIGNAL_EMIT "elm,action,decrement,start" "";
+           }
+           program { name: "dec2";
+               signal: "mouse,up,1";
+               source: "down_bt";
+               action: SIGNAL_EMIT "elm,action,decrement,stop" "";
+           }
+           program { name: "inc";
+               signal: "mouse,down,1";
+               source: "up_bt";
+               action: SIGNAL_EMIT "elm,action,increment,start" "";
+           }
+           program { name: "inc2";
+               signal: "mouse,up,1";
+               source: "up_bt";
+               action: SIGNAL_EMIT "elm,action,increment,stop" "";
+           }
+           program {
+               name:   "down_bt_click2";
+               signal: "mouse,down,1";
+               source: "down_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "down_over3";
+           }
+           program {
+               name:   "down_bt_unclick2";
+               signal: "mouse,up,1";
+               source: "down_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "down_over3";
+           }
+           program {
+               name:   "up_bt_click2";
+               signal: "mouse,down,1";
+               source: "up_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "up_over3";
+           }
+           program {
+               name:   "up_bt_unclick2";
+               signal: "mouse,up,1";
+               source: "up_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "up_over3";
+           }
+           program { name: "disable";
+               signal: "elm,state,disabled";
+               source: "elm";
+               action: STATE_SET "disabled" 0.0;
+               target: "down_bt";
+               target: "up_bt";
+               target: "disabler";
+               after: "disable_text";
+           }
+           program { name: "disable_text";
+               script {
+                   new st[31];
+                   new Float:vl;
+                   get_state(PART:"elm.text", st, 30, vl);
+                   if (!strcmp(st, "active"))
+                   set_state(PART:"elm.text", "disabled_active", 0.0);
+                   else
+                   set_state(PART:"elm.text", "disabled", 0.0);
+
+                   get_state(PART:"elm.swallow.entry", st, 30, vl);
+                   if (!strcmp(st, "active"))
+                   set_state(PART:"elm.swallow.entry", "disabled_active", 0.0);
+                   else
+                   set_state(PART:"elm.swallow.entry", "disabled", 0.0);
+               }
+           }
+           program { name: "enable";
+               signal: "elm,state,enabled";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "down_bt";
+               target: "up_bt";
+               target: "disabler";
+               after: "enable_text";
+           }
+           program { name: "enable_text";
+               script {
+                   new st[31];
+                   new Float:vl;
+                   get_state(PART:"elm.text", st, 30, vl);
+                   if (!strcmp(st, "disabled_active"))
+                   set_state(PART:"elm.text", "active", 0.0);
+                   else
+                   set_state(PART:"elm.text", "default", 0.0);
+
+                   get_state(PART:"elm.swallow.entry", st, 30, vl);
+                   if (!strcmp(st, "disabled_active"))
+                   set_state(PART:"elm.swallow.entry", "active", 0.0);
+                   else
+                   set_state(PART:"elm.swallow.entry", "default", 0.0);
+               }
+           }
+           program { name: "active";
+               signal: "elm,state,active";
+               source: "elm";
+               action: STATE_SET "active" 0.0;
+               target: "elm.text";
+               target: "elm.swallow.entry";
+           }
+           program { name: "inactive";
+               signal: "elm,state,inactive";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "elm.text";
+               target: "elm.swallow.entry";
+           }
+           program { name: "toggle_text";
+               signal: "mouse,up,1";
+               source: "button_events";
+               action: SIGNAL_EMIT "elm,action,entry,toggle" "";
+           }
+       }
+   }
+
+
+   ///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/index/base/vertical/default";
+       images {
+           image: "bt_base1.png" COMP;
+           image: "bt_base2.png" COMP;
+           image: "bt_hilight.png" COMP;
+           image: "bt_shine.png" COMP;
+       }
+       parts {
+           part { name: "clip";
+               type: RECT;
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   visible:  0;
+                   color: 255 255 255 0;
+               }
+               description { state: "active" 0.0;
+                   visible:  1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "clip2";
+               type: RECT;
+               mouse_events:  0;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+               description { state: "active" 0.0;
+                   visible:  1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "elm.swallow.index.0";
+               type: SWALLOW;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   align: 1.0 0.5;
+                   fixed: 1 1;
+                   rel1 {
+                       relative: 1.0 0.5;
+                       offset: -1 5;
+                   }
+                   rel2 {
+                       relative: 1.0 0.5;
+                       offset: -1 -6;
+                   }
+               }
+           }
+           part { name: "button_image";
+               mouse_events: 1;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "elm.text.body";
+                       offset: -5 -5;
+                   }
+                   rel2 {
+                       to: "elm.text";
+                       offset: 4 4;
+                   }
+                   image {
+                       normal: "bt_base2.png";
+                       border: 7 7 7 7;
+                   }
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "elm.text.body";
+               type: TEXT;
+               effect: SOFT_SHADOW;
+               mouse_events: 0;
+               scale: 1;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   align: 1.0 0.5;
+                   fixed: 1 1;
+                   rel1 {
+                       to: "elm.text";
+                       relative: 0.0 0.0;
+                       offset: 5 0;
+                   }
+                   rel2 {
+                       to: "elm.text";
+                       relative: 0.0 1.0;
+                       offset: 5 -1;
+                   }
+                   color: 224 224 224 255;
+                   color3: 0 0 0 64;
+                   text {
+                       font:     "Sans,Edje-Vera";
+                       size:     20;
+                       min:      1 1;
+                       align:    1.0 0.5;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               type: TEXT;
+               effect: SOFT_SHADOW;
+               mouse_events: 0;
+               scale: 1;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   align: 1.0 0.5;
+                   fixed: 1 1;
+                   rel1 {
+                       to_x: "elm.swallow.event.0";
+                       to_y: "elm.dragable.pointer";
+                       relative: 0.0 0.5;
+                       offset: -16 0;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.event.0";
+                       to_y: "elm.dragable.pointer";
+                       relative: 0.0 0.5;
+                       offset: -16 -1;
+                   }
+                   color: 255 0 0 255;
+                   color3: 0 0 0 64;
+                   text {
+                       font:     "Sans,Edje-Vera";
+                       size:     20;
+                       min:      1 1;
+                       align:    1.0 0.5;
+                   }
+               }
+           }
+           part {      name: "over1";
+               mouse_events: 0;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "button_image";
+                   }
+                   rel2 {
+                       to: "button_image";
+                       relative: 1.0 0.5;
+                   }
+                   image {
+                       normal: "bt_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+           }
+           part { name: "over2";
+               mouse_events: 1;
+               repeat_events: 1;
+               ignore_flags: ON_HOLD;
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "button_image";
+                   }
+                   rel2 {
+                       to: "button_image";
+                   }
+                   image {
+                       normal: "bt_shine.png";
+                       border: 7 7 7 7;
+                   }
+               }
+           }
+           part { name: "elm.dragable.pointer";
+               type: RECT;
+               mouse_events: 0;
+               dragable {
+                   x: 1 1 0;
+                   y: 1 1 0;
+               }
+               clip_to: "clip";
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   min: 8 8;
+                   max: 8 8;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset:   0 0;
+                   }
+                   rel2 {
+                       relative: 0.0 0.0;
+                       offset:   0 0;
+                   }
+                   color: 0 0 255 128;
+               }
+           }
+           part { name: "elm.swallow.event.0";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   align: 1.0 0.5;
+                   fixed: 1 1;
+                   rel1 {
+                       relative: 1.0 0.0;
+                       offset: -1 0;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: -1 -1;
+                   }
+               }
+           }
+       }
+       programs {
+           program { name: "active";
+               signal: "elm,state,active";
+               source: "elm";
+               action: STATE_SET "active" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+           }
+           program { name: "inactive";
+               signal: "elm,state,inactive";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "clip";
+           }
+       }
+   }
+
+   group { name: "elm/index/item/vertical/default";
+       data.item: "stacking" "above";
+       data.item: "selectraise" "on";
+       images {
+           image: "ilist_1.png" COMP;
+           image: "ilist_item_shadow.png" COMP;
+       }
+       parts {
+           part {
+               name: "base_sh";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.0;
+                   min: 0 10;
+                   fixed: 1 1;
+                   rel1 {
+                       to: "base";
+                       relative: 0.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "base";
+                       relative: 1.0 1.0;
+                       offset: -1 0;
+                   }
+                   image {
+                       normal: "ilist_item_shadow.png";
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part {
+               name: "base";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   image {
+                       normal: "ilist_1.png";
+                       border: 2 2 2 2;
+                   }
+                   fill.smooth: 0;
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   rel1 {
+                       offset: -16 0;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               type:           TEXT;
+               mouse_events:   0;
+               scale: 1;
+               description {
+                   state: "default" 0.0;
+                          //               min: 16 16;
+                   rel1 {
+                       to: "base";
+                       relative: 0.0  0.0;
+                       offset:   4 4;
+                   }
+                   rel2 {
+                       to: "base";
+                       relative: 1.0  1.0;
+                       offset:   -5 -5;
+                   }
+                   color: 0 0 0 128;
+                   text {
+                       font: "Sans";
+                       size: 10;
+                       min: 1 1;
+                            //                  min: 0 1;
+                       align: 0.0 0.5;
+                   }
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 255;
+               }
+           }
+       }
+       programs {
+           program { name: "active";
+               signal: "elm,state,active";
+               source: "elm";
+               action: STATE_SET "active" 0.0;
+               transition: DECELERATE 0.5;
+               target: "elm.text";
+               target: "base";
+           }
+           program { name: "inactive";
+               signal: "elm,state,inactive";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "elm.text";
+               target: "base";
+           }
+       }
+   }
+
+   group { name: "elm/index/item_odd/vertical/default";
+       data.item: "stacking" "below";
+       images {
+           image: "ilist_2.png" COMP;
+       }
+       parts {
+           part {
+               name: "base";
+               mouse_events: 0;
+               description {
+                   state: "default" 0.0;
+                   image {
+                       normal: "ilist_2.png";
+                       border: 2 2 2 2;
+                   }
+                   fill.smooth: 0;
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   rel1 {
+                       offset: -16 0;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               type:           TEXT;
+               mouse_events:   0;
+               scale: 1;
+               description {
+                   state: "default" 0.0;
+                          //               min: 16 16;
+                   rel1 {
+                       to: "base";
+                       relative: 0.0  0.0;
+                       offset:   4 4;
+                   }
+                   rel2 {
+                       to: "base";
+                       relative: 1.0  1.0;
+                       offset:   -5 -5;
+                   }
+                   color: 0 0 0 128;
+                   text {
+                       font: "Sans";
+                       size: 10;
+                       min: 1 1;
+                            //                  min: 0 1;
+                       align: 0.0 0.5;
+                   }
+               }
+               description { state: "active" 0.0;
+                   inherit: "default" 0.0;
+                   color: 0 0 0 255;
+               }
+           }
+       }
+       programs {
+           program { name: "active";
+               signal: "elm,state,active";
+               source: "elm";
+               action: STATE_SET "active" 0.0;
+               transition: DECELERATE 0.5;
+               target: "elm.text";
+               target: "base";
+           }
+           program { name: "inactive";
+               signal: "elm,state,inactive";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "elm.text";
+               target: "base";
+           }
+       }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/gengrid/item/default/default";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon elm.swallow.end";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "ilist_1.png" COMP;
+         image: "ilist_item_shadow.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description {
+               state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part { name: "base_sh";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 0 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -1 0;
+               }
+               image {
+                  normal: "ilist_item_shadow.png";
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "base";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               image {
+                  normal: "ilist_1.png";
+                  border: 2 2 2 2;
+               }
+               fill.smooth: 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 4 4;
+               }
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+               }
+               image.middle: SOLID;
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: -2 -2;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 1 1;
+               }
+            }
+         }
+         part { name: "elm.swallow.pad";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0.0  1.0;
+                  offset:   0    -10;
+               }
+               rel2 {
+                 to_y: "elm.text";
+                  relative: 0.0  0.0;
+                  offset:   -1   -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.5 0.5;
+               rel1 {
+                  relative: 0.0  0.0;
+                  offset:   -1    4;
+               }
+               rel2 {
+                  to_y: "elm.swallow.pad";
+                  relative: 1.0  0.0;
+                  offset:   -1   -5;
+               }
+            }
+         }
+         part { name: "elm.swallow.end";
+            clip_to: "disclip";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 1.0 0.0;
+               aspect: 1.0 1.0;
+               aspect_preference: HORIZONTAL;
+               rel1 {
+                  relative: 1.0 0.0;
+                  offset: -5 -5;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: 5 5;
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset: -5 -5;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.5 0.0;
+                  text_class: "grid_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.relative: 1.0 0.5;
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         // signal: elm,state,%s,active
+         //   a "check" item named %s went active
+         // signal: elm,state,%s,passive
+         //   a "check" item named %s went passive
+         // default is passive
+         program { name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program { name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program { name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program { name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+   group { name: "elm/gengrid/item/default_style/default";
+       styles
+       {
+           style { name: "gengrid_style";
+               base: "font=Sans font_size=10 align=left valign=0.5 color=#000 text_class=grid_item";
+               tag:  "br" "\n";
+               tag:  "ps" "ps";
+               tag:  "hilight" "+ font=Sans:style=Bold";
+               tag:  "b" "+ font=Sans:style=Bold";
+               tag:  "tab" "\t";
+           }
+           style { name: "gengrid_selected_style";
+               base: "font=Sans font_size=10 align=left valign=0.5 color=#fff text_class=grid_item";
+               tag:  "br" "\n";
+               tag:  "ps" "ps";
+               tag:  "hilight" "+ font=Sans:style=Bold";
+               tag:  "b" "+ font=Sans:style=Bold";
+               tag:  "tab" "\t";
+           }
+       }
+       data.item: "labels" "elm.text";
+       data.item: "icons" "elm.swallow.icon elm.swallow.end";
+       images {
+           image: "bt_sm_base1.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "ilist_1.png" COMP;
+           image: "ilist_item_shadow.png" COMP;
+       }
+       parts {
+           part { name: "event";
+               type: RECT;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "base_sh";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   align: 0.0 0.0;
+                   min: 0 10;
+                   fixed: 1 1;
+                   rel1 {
+                       to: "base";
+                       relative: 0.0 1.0;
+                       offset: 0 0;
+                   }
+                   rel2 {
+                       to: "base";
+                       relative: 1.0 1.0;
+                       offset: -1 0;
+                   }
+                   image {
+                       normal: "ilist_item_shadow.png";
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "base";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   min: 16 28;
+                   image {
+                       normal: "ilist_1.png";
+                       border: 2 2 2 2;
+                   }
+                   fill.smooth: 0;
+               }
+           }
+           part { name: "bg";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -5 -5;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 4 4;
+                   }
+                   image {
+                       normal: "bt_sm_base1.png";
+                       border: 6 6 6 6;
+                   }
+                   image.middle: SOLID;
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+                   rel1 {
+                       relative: 0.0 0.0;
+                       offset: -2 -2;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: 1 1;
+                   }
+               }
+           }
+           part { name: "elm.swallow.pad";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       relative: 0.0  0.0;
+                       offset:   4    4;
+                   }
+                   rel2 {
+                       relative: 0.0  1.0;
+                       offset:   4   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.icon";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 0.0 0.5;
+                   rel1 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  0.0;
+                       offset:   -1    4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.pad";
+                       relative: 1.0  1.0;
+                       offset:   -1   -5;
+                   }
+               }
+           }
+           part { name: "elm.swallow.end";
+               clip_to: "disclip";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   fixed: 1 0;
+                   align: 1.0 0.5;
+                   aspect: 1.0 1.0;
+                   aspect_preference: VERTICAL;
+                   rel1 {
+                       relative: 1.0  0.0;
+                       offset:   -5    4;
+                   }
+                   rel2 {
+                       relative: 1.0  1.0;
+                       offset:   -5   -5;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               clip_to: "disclip";
+               type: TEXTBLOCK;
+               mouse_events: 0;
+               scale: 1;
+               description {
+                   state: "default" 0.0;
+                   align: 0.0 0.5;
+                   fixed: 0 1;
+                   rel1 {
+                       to_x: "elm.swallow.icon";
+                       to_y: "base";
+                       relative: 1.0  0.5;
+                       offset:   0 4;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.end";
+                       to_y: "base";
+                       relative: 0.0  0.5;
+                       offset:   -1 -5;
+                   }
+                   text {
+                       style: "gengrid_style";
+                       min: 1 1;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   text {
+                       style: "gengrid_selected_style";
+                   }
+               }
+           }
+           part { name: "fg1";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "fg2";
+               clip_to: "disclip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "disclip";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+               }
+               description { state: "disabled" 0.0;
+                   inherit: "default" 0.0;
+                   color: 255 255 255 64;
+               }
+           }
+       }
+       programs {
+           // signal: elm,state,%s,active
+           //   a "check" item named %s went active
+           // signal: elm,state,%s,passive
+           //   a "check" item named %s went passive
+           // default is passive
+           program { name:    "go_active";
+               signal:  "elm,state,selected";
+               source:  "elm";
+               action:  STATE_SET "selected" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+           }
+           program { name:    "go_passive";
+               signal:  "elm,state,unselected";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "bg";
+               target:  "fg1";
+               target:  "fg2";
+               target:  "elm.text";
+               transition: LINEAR 0.1;
+           }
+           program { name:    "go_disabled";
+               signal:  "elm,state,disabled";
+               source:  "elm";
+               action:  STATE_SET "disabled" 0.0;
+               target:  "disclip";
+           }
+           program { name:    "go_enabled";
+               signal:  "elm,state,enabled";
+               source:  "elm";
+               action:  STATE_SET "default" 0.0;
+               target:  "disclip";
+           }
+       }
+   }
+
+   group { name: "elm/gengrid/item/up/default";
+      data.item: "labels" "elm.text";
+      images {
+          image: "bt_sm_base1.png" COMP;
+          image: "bt_sm_shine.png" COMP;
+          image: "bt_sm_hilight.png" COMP;
+          image: "arrow_up.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.offset: -3 -3;
+               rel2.offset: 2 2;
+               image { normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+                  middle: SOLID;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "image";
+             type: IMAGE;
+             mouse_events: 0;
+             description { state: "default" 0.0;
+                 aspect_preference: BOTH;
+                 aspect: 1.0 1.0;
+                 image.normal: "arrow_up.png";
+                 rel2 {
+                     to_y: "elm.text";
+                     relative: 1.0 0.0;
+                     offset: -1 -2;
+                 }
+             }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  1.0;
+                  offset: 20 -25;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset: -21 -3;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.5 0.0;
+                  text_class: "grid_item";
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               color: 224 224 224 255;
+               color3: 0 0 0 64;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.offset: -3 -3;
+               rel2 {
+                   relative: 1.0 0.5;
+                   offset: 2 -1;
+               }
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.offset: -3 -3;
+               rel2.offset: 2 2;
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         program { name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program { name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program { name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program { name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+      }
+   }
+
+   group { name: "elm/gengrid/item/album-preview/default";
+      data.item: "labels" "elm.text";
+      data.item: "icons" "elm.swallow.icon.1 elm.swallow.icon.2 elm.swallow.icon.3 elm.swallow.icon.4";
+      data.item: "states" "have_files";
+      images {
+         image: "bt_sm_base1.png" COMP;
+         image: "bt_sm_shine.png" COMP;
+         image: "bt_sm_hilight.png" COMP;
+         image: "icon_folder.png" COMP;
+      }
+      parts {
+         part { name: "event";
+            type: RECT;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part { name: "bg";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.offset: -3 -3;
+               rel2.offset: 2 2;
+               image {
+                  normal: "bt_sm_base1.png";
+                  border: 6 6 6 6;
+                  middle: SOLID;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "image";
+             type: IMAGE;
+             mouse_events: 0;
+             description { state: "default" 0.0;
+                 aspect_preference: BOTH;
+                 aspect: 1.0 1.0;
+                 image.normal: "icon_folder.png";
+                 rel2 {
+                     to_y: "elm.text";
+                     relative: 1.0 0.0;
+                     offset: -1 -2;
+                 }
+             }
+         }
+         part { name: "have-files-clipper";
+             type: RECT;
+             description { state: "default" 0.0;
+                 color: 255 255 255 0;
+                 visible: 0;
+             }
+             description { state: "visible" 0.0;
+                 inherit: "default" 0.0;
+                 color: 255 255 255 255;
+                 visible: 1;
+             }
+         }
+         part { name: "icon_box_margin";
+             type: RECT;
+             mouse_events: 0;
+             clip_to: "have-files-clipper";
+             description { state: "default" 0.0;
+                 color: 0 0 0 255;
+                 rel1 {
+                     to: "icon_box";
+                     offset: -1 -1;
+                 }
+                 rel2 {
+                     to: "icon_box";
+                     offset: 0 0;
+                 }
+             }
+         }
+         part { name: "icon_box";
+             type: RECT;
+             mouse_events: 0;
+             clip_to: "have-files-clipper";
+             description { state: "default" 0.0;
+                 color: 255 255 255 255;
+                 align: 1.0 1.0;
+                 min: 32 32;
+                 rel1 {
+                     relative: 0.25 0.25;
+                     offset: 0 0;
+                 }
+                 rel2 {
+                     relative: 1.0 0.0;
+                     offset: -11 -4;
+                     to_y: "elm.text";
+                 }
+             }
+         }
+         part { name: "elm.swallow.icon.1";
+             type: SWALLOW;
+             mouse_events: 0;
+             clip_to: "have-files-clipper";
+             description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.0;
+                  to: "icon_box";
+               }
+               rel2 {
+                  relative: 0.5  0.5;
+                  offset: -1 -1;
+                  to: "icon_box";
+               }
+            }
+         }
+         part { name: "elm.swallow.icon.2";
+             type: SWALLOW;
+             mouse_events: 0;
+             clip_to: "have-files-clipper";
+             description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.5  0.0;
+                  to: "icon_box";
+               }
+               rel2 {
+                  relative: 1.0  0.5;
+                  offset: -1 -1;
+                  to: "icon_box";
+               }
+            }
+         }
+         part { name: "elm.swallow.icon.3";
+             type: SWALLOW;
+             mouse_events: 0;
+             clip_to: "have-files-clipper";
+             description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  0.5;
+                  to: "icon_box";
+               }
+               rel2 {
+                  relative: 0.5  1.0;
+                  offset: -1 -1;
+                  to: "icon_box";
+               }
+            }
+         }
+         part { name: "elm.swallow.icon.4";
+             type: SWALLOW;
+             mouse_events: 0;
+             clip_to: "have-files-clipper";
+             description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.5  0.5;
+                  to: "icon_box";
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset: -1 -1;
+                  to: "icon_box";
+               }
+            }
+         }
+         part { name: "elm.text";
+            clip_to: "disclip";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  relative: 0.0  1.0;
+                  offset: 20 -30;
+               }
+               rel2 {
+                  relative: 1.0  1.0;
+                  offset: -21 -15;
+               }
+               color: 0 0 0 255;
+               color3: 0 0 0 0;
+               text {
+                  font: "Sans";
+                  size: 10;
+                  min: 0 1;
+                  align: 0.5 0.0;
+                  text_class: "grid_item";
+               }
+            }
+            description { state: "selected" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 255;
+            }
+         }
+         part { name: "fg1";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.offset: -3 -3;
+               rel2 {
+                   relative: 1.0 0.5;
+                   offset: 2 -1;
+               }
+               image {
+                  normal: "bt_sm_hilight.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "fg2";
+            clip_to: "disclip";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               visible: 0;
+               color: 255 255 255 0;
+               rel1.offset: -3 -3;
+               rel2.offset: 2 2;
+               image {
+                  normal: "bt_sm_shine.png";
+                  border: 6 6 6 0;
+               }
+            }
+            description { state: "selected" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "disclip";
+            type: RECT;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+            description { state: "disabled" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 64;
+            }
+         }
+      }
+      programs {
+         program { name:    "go_active";
+            signal:  "elm,state,selected";
+            source:  "elm";
+            action:  STATE_SET "selected" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+         }
+         program { name:    "go_passive";
+            signal:  "elm,state,unselected";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "bg";
+            target:  "fg1";
+            target:  "fg2";
+            target:  "elm.text";
+            transition: LINEAR 0.1;
+         }
+         program { name:    "go_disabled";
+            signal:  "elm,state,disabled";
+            source:  "elm";
+            action:  STATE_SET "disabled" 0.0;
+            target:  "disclip";
+         }
+         program { name:    "go_enabled";
+            signal:  "elm,state,enabled";
+            source:  "elm";
+            action:  STATE_SET "default" 0.0;
+            target:  "disclip";
+         }
+         program {
+             signal: "elm,state,have_files,active";
+             source: "elm";
+             action: STATE_SET "visible" 0.0;
+             target: "have-files-clipper";
+         }
+      }
+   }
+
+   group { name: "elm/gengrid/item/thumb/default";
+       data {
+           item: "icons" "elm.swallow.icon";
+           item: "labels" "elm.text";
+       }
+       images {
+           image: "bt_sm_base1.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "thumb_shadow.png" COMP;
+       }
+       parts {
+           part { name: "event";
+               type: RECT;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 0;
+               }
+           }
+           part { name: "bg";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.offset: -3 -3;
+                   rel2.offset: 2 2;
+                   image {
+                       normal: "bt_sm_base1.png";
+                       border: 6 6 6 6;
+                       middle: SOLID;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "border-shadow";
+               type: IMAGE;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "elm.swallow.icon";
+                       offset: -18 -18;
+                   }
+                   rel2 {
+                       to_x: "elm.swallow.icon";
+                       to_y: "elm.text";
+                       offset: 17 17;
+                   }
+                   image {
+                       normal: "thumb_shadow.png";
+                       border: 17 17 17 17;
+                       middle: NONE;
+                   }
+               }
+           }
+           part { name: "border";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1 {
+                       to: "border-shadow";
+                       offset: 16 16;
+                   }
+                   rel2 {
+                       to: "border-shadow";
+                       offset: -15 -15;
+                   }
+               }
+           }
+           part { name: "elm.swallow.icon";
+               type: SWALLOW;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   aspect_preference: BOTH;
+                   aspect: 1.0 1.0;
+                   rel1.offset: 0 8;
+                   rel2 {
+                       to_y: "elm.text";
+                       relative: 1.0 0.0;
+                       offset: -1 -2;
+                   }
+               }
+           }
+           part { name: "elm.text";
+               type: TEXT;
+               effect: SOFT_SHADOW;
+               mouse_events: 0;
+               scale: 1;
+               description { state: "default" 0.0;
+                   color: 0 0 0 255;
+                   color3: 0 0 0 0;
+                   align: 0.5 1.0;
+                   rel1 {
+                       relative: 0.0 1.0;
+                       offset: 20 -30;
+                   }
+                   rel2 {
+                       relative: 1.0 1.0;
+                       offset: -21 -15;
+                   }
+                   text {
+                       font: "Sans";
+                       size: 10;
+                       min: 0 1;
+                       align: 0.5 0.0;
+                       text_class: "grid_item";
+                   }
+               }
+           }
+           part { name: "fg1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.offset: -3 -3;
+                   rel2 {
+                       relative: 1.0 0.5;
+                       offset: 2 -1;
+                   }
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "fg2";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+                   rel1.offset: -3 -3;
+                   rel2.offset: 2 2;
+                   image {
+                       image: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+               description { state: "selected" 0.0;
+                   inherit: "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+       }
+       programs {
+           program {
+               signal: "elm,state,selected";
+               source: "elm";
+               action: STATE_SET "selected" 0.0;
+               target: "bg";
+               target: "fg1";
+               target: "fg2";
+           }
+           program {
+               signal: "elm,state,unselected";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "bg";
+               target: "fg1";
+               target: "fg2";
+               transition: LINEAR 0.1;
+           }
+       }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/photocam/base/default";
+       script {
+           public sbvis_v, sbvis_h, sbalways_v, sbalways_h, sbvis_timer;
+           public timer0(val) {
+               new v;
+               v = get_int(sbvis_v);
+               if (v) {
+                   v = get_int(sbalways_v);
+                   if (!v) {
+                       emit("do-hide-vbar", "");
+                       set_int(sbvis_v, 0);
+                   }
+               }
+               v = get_int(sbvis_h);
+               if (v) {
+                   v = get_int(sbalways_h);
+                   if (!v) {
+                       emit("do-hide-hbar", "");
+                       set_int(sbvis_h, 0);
+                   }
+               }
+               set_int(sbvis_timer, 0);
+               return 0;
+           }
+       }
+       images {
+           image: "shelf_inset.png" COMP;
+           image: "bt_sm_base2.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "busy-1.png" COMP;
+           image: "busy-2.png" COMP;
+           image: "busy-3.png" COMP;
+           image: "busy-4.png" COMP;
+           image: "busy-5.png" COMP;
+           image: "busy-6.png" COMP;
+           image: "busy-7.png" COMP;
+           image: "busy-8.png" COMP;
+           image: "busy-9.png" COMP;
+       }
+       parts {
+           part { name: "bg";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.offset: 1 1;
+                   rel2.offset: -2 -2;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "clipper";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+               }
+           }
+           part { name: "elm.swallow.content";
+               clip_to: "clipper";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.offset: 1 1;
+                   rel2.offset: -2 -2;
+               }
+           }
+           part { name: "busy_clip";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+               description { state: "active" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "busy";
+               clip_to: "busy_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   min: 32 32;
+                   aspect: 1.0 1.0;
+                   align: 1.0 1.0;
+                   aspect_preference: BOTH;
+                   rel1 {
+                       relative: 0.9 0.9;
+                       offset:   -9 -9;
+                   }
+                   rel2 {
+                       relative: 0.9 0.9;
+                       offset:   -9 -9;
+                   }
+                   image {
+                       normal: "busy-9.png";
+                       tween:  "busy-1.png";
+                       tween:  "busy-2.png";
+                       tween:  "busy-3.png";
+                       tween:  "busy-4.png";
+                       tween:  "busy-5.png";
+                       tween:  "busy-6.png";
+                       tween:  "busy-7.png";
+                       tween:  "busy-8.png";
+                   }
+               }
+           }
+           part { name: "conf_over";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   rel1.offset: 0 0;
+                   rel2.offset: -1 -1;
+                   image {
+                       normal: "shelf_inset.png";
+                       border: 7 7 7 7;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "sb_vbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_vbar_clip";
+               clip_to: "sb_vbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_vbar";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   visible: 0;
+                   min: 10 17;
+                   align: 1.0 0.0;
+                   rel1 {
+                       relative: 1.0 0.0;
+                       offset:   -2 0;
+                   }
+                   rel2 {
+                       relative: 1.0 0.0;
+                       offset:   -2 -1;
+                       to_y:     "sb_hbar";
+                   }
+               }
+           }
+           part { name: "elm.dragable.vbar";
+               clip_to: "sb_vbar_clip";
+               mouse_events: 0;
+               dragable {
+                   x: 0 0 0;
+                   y: 1 1 0;
+                   confine: "sb_vbar";
+               }
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   min: 10 17;
+                   max: 10 99999;
+                   rel1 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_vbar";
+                   }
+                   rel2 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_vbar";
+                   }
+                   image {
+                       normal: "bt_sm_base2.png";
+                       border: 6 6 6 6;
+                       middle: SOLID;
+                   }
+               }
+           }
+           part { name: "sb_vbar_over1";
+               clip_to: "sb_vbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.vbar";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "elm.dragable.vbar";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+           }
+           part { name: "sb_vbar_over2";
+               clip_to: "sb_vbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.vbar";
+                   rel2.to: "elm.dragable.vbar";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+           }
+
+           part { name: "sb_hbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_hbar_clip";
+               clip_to: "sb_hbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_hbar";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   visible: 0;
+                   min: 17 10;
+                   align: 0.0 1.0;
+                   rel1 {
+                       relative: 0.0 1.0;
+                       offset:   0 -2;
+                   }
+                   rel2 {
+                       relative: 0.0 1.0;
+                       offset:   -1 -2;
+                       to_x:     "sb_vbar";
+                   }
+               }
+           }
+           part { name: "elm.dragable.hbar";
+               clip_to: "sb_hbar_clip";
+               mouse_events: 0;
+               dragable {
+                   x: 1 1 0;
+                   y: 0 0 0;
+                   confine: "sb_hbar";
+               }
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   min: 17 10;
+                   max: 99999 10;
+                   rel1 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_hbar";
+                   }
+                   rel2 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_hbar";
+                   }
+                   image {
+                       normal: "bt_sm_base2.png";
+                       border: 4 4 4 4;
+                       middle: SOLID;
+                   }
+               }
+           }
+           part { name: "sb_hbar_over1";
+               clip_to: "sb_hbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.hbar";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "elm.dragable.hbar";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "sb_hbar_over2";
+               clip_to: "sb_hbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.hbar";
+                   rel2.to: "elm.dragable.hbar";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+       }
+       programs {
+           program { name: "load";
+               signal: "load";
+               source: "";
+               script {
+                   set_state(PART:"sb_hbar_clip", "hidden", 0.0);
+                   set_state(PART:"sb_vbar_clip", "hidden", 0.0);
+                   set_int(sbvis_h, 0);
+                   set_int(sbvis_v, 0);
+                   set_int(sbalways_v, 0);
+                   set_int(sbalways_h, 0);
+                   set_int(sbvis_timer, 0);
+               }
+           }
+
+           program { name: "vbar_show";
+               signal: "elm,action,show,vbar";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "sb_vbar_clip_master";
+           }
+           program { name: "vbar_hide";
+               signal: "elm,action,hide,vbar";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "sb_vbar_clip_master";
+           }
+           program { name: "vbar_show_always";
+               signal: "elm,action,show_always,vbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbvis_v);
+                   v |= get_int(sbalways_v);
+                   if (!v) {
+                       set_int(sbalways_v, 1);
+                       emit("do-show-vbar", "");
+                       set_int(sbvis_v, 1);
+                   }
+               }
+           }
+           program { name: "vbar_show_notalways";
+               signal: "elm,action,show_notalways,vbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbalways_v);
+                   if (v) {
+                       set_int(sbalways_v, 0);
+                       v = get_int(sbvis_v);
+                       if (!v) {
+                           emit("do-hide-vbar", "");
+                           set_int(sbvis_v, 0);
+                       }
+                   }
+               }
+           }
+           program { name: "sb_vbar_show";
+               signal: "do-show-vbar";
+               source: "";
+               action:  STATE_SET "default" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_vbar_clip";
+           }
+           program { name: "sb_vbar_hide";
+               signal: "do-hide-vbar";
+               source: "";
+               action:  STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_vbar_clip";
+           }
+
+           program { name: "hbar_show";
+               signal: "elm,action,show,hbar";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "sb_hbar_clip_master";
+           }
+           program { name: "hbar_hide";
+               signal: "elm,action,hide,hbar";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "sb_hbar_clip_master";
+           }
+           program { name: "hbar_show_always";
+               signal: "elm,action,show_always,hbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbvis_h);
+                   v |= get_int(sbalways_h);
+                   if (!v) {
+                       set_int(sbalways_h, 1);
+                       emit("do-show-hbar", "");
+                       set_int(sbvis_h, 1);
+                   }
+               }
+           }
+           program { name: "hbar_show_notalways";
+               signal: "elm,action,show_notalways,hbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbalways_h);
+                   if (v) {
+                       set_int(sbalways_h, 0);
+                       v = get_int(sbvis_h);
+                       if (!v) {
+                           emit("do-hide-hbar", "");
+                           set_int(sbvis_h, 0);
+                       }
+                   }
+               }
+           }
+           program { name: "sb_hbar_show";
+               signal: "do-show-hbar";
+               source: "";
+               action:  STATE_SET "default" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_hbar_clip";
+           }
+           program { name: "sb_hbar_hide";
+               signal: "do-hide-hbar";
+               source: "";
+               action:  STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_hbar_clip";
+           }
+
+           program { name: "scroll";
+               signal: "elm,action,scroll";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbvis_v);
+                   v |= get_int(sbalways_v);
+                   if (!v) {
+                       emit("do-show-vbar", "");
+                       set_int(sbvis_v, 1);
+                   }
+                   v = get_int(sbvis_h);
+                   v |= get_int(sbalways_h);
+                   if (!v) {
+                       emit("do-show-hbar", "");
+                       set_int(sbvis_h, 1);
+                   }
+                   v = get_int(sbvis_timer);
+                   if (v > 0) cancel_timer(v);
+                   v = timer(1.0, "timer0", 0);
+                   set_int(sbvis_timer, v);
+               }
+           }
+           program { name: "go1";
+               signal: "elm,state,busy,start";
+               source: "elm";
+               action: STATE_SET "active" 0.0;
+               transition: SINUSOIDAL 1.0;
+               target:  "busy_clip";
+           }
+           program { name: "go2";
+               signal: "elm,state,busy,start";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: LINEAR 0.5;
+               target: "busy";
+               after:  "go2";
+           }
+           program { name: "stop1";
+               signal: "elm,state,busy,stop";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: SINUSOIDAL 1.0;
+               target: "busy_clip";
+               after: "stop2";
+           }
+         program { name: "stop2";
+            action: ACTION_STOP;
+            target: "go2";
+         }
+      }
+   }
+
+   ///////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/map/base/default";
+       script {
+           public sbvis_v, sbvis_h, sbalways_v, sbalways_h, sbvis_timer;
+           public timer0(val) {
+               new v;
+               v = get_int(sbvis_v);
+               if (v) {
+                   v = get_int(sbalways_v);
+                   if (!v) {
+                       emit("do-hide-vbar", "");
+                       set_int(sbvis_v, 0);
+                   }
+               }
+               v = get_int(sbvis_h);
+               if (v) {
+                   v = get_int(sbalways_h);
+                   if (!v) {
+                       emit("do-hide-hbar", "");
+                       set_int(sbvis_h, 0);
+                   }
+               }
+               set_int(sbvis_timer, 0);
+               return 0;
+           }
+       }
+       images {
+           image: "shelf_inset.png" COMP;
+           image: "bt_sm_base2.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "busy-1.png" COMP;
+           image: "busy-2.png" COMP;
+           image: "busy-3.png" COMP;
+           image: "busy-4.png" COMP;
+           image: "busy-5.png" COMP;
+           image: "busy-6.png" COMP;
+           image: "busy-7.png" COMP;
+           image: "busy-8.png" COMP;
+           image: "busy-9.png" COMP;
+       }
+       parts {
+           part { name: "bg";
+               type: RECT;
+               description { state: "default" 0.0;
+                   rel1.offset: 1 1;
+                   rel2.offset: -2 -2;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "clipper";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "bg";
+                   rel2.to: "bg";
+               }
+           }
+           part { name: "elm.swallow.content";
+               clip_to: "clipper";
+               type: SWALLOW;
+               description { state: "default" 0.0;
+                   rel1.offset: 1 1;
+                   rel2.offset: -2 -2;
+               }
+           }
+           part { name: "busy_clip";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+               description { state: "active" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "busy";
+               clip_to: "busy_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   min: 32 32;
+                   aspect: 1.0 1.0;
+                   align: 1.0 1.0;
+                   aspect_preference: BOTH;
+                   rel1 {
+                       relative: 0.9 0.9;
+                       offset:   -9 -9;
+                   }
+                   rel2 {
+                       relative: 0.9 0.9;
+                       offset:   -9 -9;
+                   }
+                   image {
+                       normal: "busy-9.png";
+                       tween:  "busy-1.png";
+                       tween:  "busy-2.png";
+                       tween:  "busy-3.png";
+                       tween:  "busy-4.png";
+                       tween:  "busy-5.png";
+                       tween:  "busy-6.png";
+                       tween:  "busy-7.png";
+                       tween:  "busy-8.png";
+                   }
+               }
+           }
+           part { name: "conf_over";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   rel1.offset: 0 0;
+                   rel2.offset: -1 -1;
+                   image {
+                       normal: "shelf_inset.png";
+                       border: 7 7 7 7;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "sb_vbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_vbar_clip";
+               clip_to: "sb_vbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_vbar";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   visible: 0;
+                   min: 10 17;
+                   align: 1.0 0.0;
+                   rel1 {
+                       relative: 1.0 0.0;
+                       offset:   -2 0;
+                   }
+                   rel2 {
+                       relative: 1.0 0.0;
+                       offset:   -2 -1;
+                       to_y:     "sb_hbar";
+                   }
+               }
+           }
+           part { name: "elm.dragable.vbar";
+               clip_to: "sb_vbar_clip";
+               mouse_events: 0;
+               dragable {
+                   x: 0 0 0;
+                   y: 1 1 0;
+                   confine: "sb_vbar";
+               }
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   min: 10 17;
+                   max: 10 99999;
+                   rel1 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_vbar";
+                   }
+                   rel2 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_vbar";
+                   }
+                   image {
+                       normal: "bt_sm_base2.png";
+                       border: 6 6 6 6;
+                       middle: SOLID;
+                   }
+               }
+           }
+           part { name: "sb_vbar_over1";
+               clip_to: "sb_vbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.vbar";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "elm.dragable.vbar";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 6 6 6 0;
+                   }
+               }
+           }
+           part { name: "sb_vbar_over2";
+               clip_to: "sb_vbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.vbar";
+                   rel2.to: "elm.dragable.vbar";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 6 6 6 0;
+                   }
+               }
+           }
+
+           part { name: "sb_hbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_hbar_clip";
+               clip_to: "sb_hbar_clip_master";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+               }
+               description { state: "hidden" 0.0;
+                   visible: 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "sb_hbar";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   visible: 0;
+                   min: 17 10;
+                   align: 0.0 1.0;
+                   rel1 {
+                       relative: 0.0 1.0;
+                       offset:   0 -2;
+                   }
+                   rel2 {
+                       relative: 0.0 1.0;
+                       offset:   -1 -2;
+                       to_x:     "sb_vbar";
+                   }
+               }
+           }
+           part { name: "elm.dragable.hbar";
+               clip_to: "sb_hbar_clip";
+               mouse_events: 0;
+               dragable {
+                   x: 1 1 0;
+                   y: 0 0 0;
+                   confine: "sb_hbar";
+               }
+               description { state: "default" 0.0;
+                   fixed: 1 1;
+                   min: 17 10;
+                   max: 99999 10;
+                   rel1 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_hbar";
+                   }
+                   rel2 {
+                       relative: 0.5  0.5;
+                       offset:   0    0;
+                       to: "sb_hbar";
+                   }
+                   image {
+                       normal: "bt_sm_base2.png";
+                       border: 4 4 4 4;
+                       middle: SOLID;
+                   }
+               }
+           }
+           part { name: "sb_hbar_over1";
+               clip_to: "sb_hbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.hbar";
+                   rel2.relative: 1.0 0.5;
+                   rel2.to: "elm.dragable.hbar";
+                   image {
+                       normal: "bt_sm_hilight.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+           part { name: "sb_hbar_over2";
+               clip_to: "sb_hbar_clip";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "elm.dragable.hbar";
+                   rel2.to: "elm.dragable.hbar";
+                   image {
+                       normal: "bt_sm_shine.png";
+                       border: 4 4 4 0;
+                   }
+               }
+           }
+       }
+       programs {
+           program { name: "load";
+               signal: "load";
+               source: "";
+               script {
+                   set_state(PART:"sb_hbar_clip", "hidden", 0.0);
+                   set_state(PART:"sb_vbar_clip", "hidden", 0.0);
+                   set_int(sbvis_h, 0);
+                   set_int(sbvis_v, 0);
+                   set_int(sbalways_v, 0);
+                   set_int(sbalways_h, 0);
+                   set_int(sbvis_timer, 0);
+               }
+           }
+
+           program { name: "vbar_show";
+               signal: "elm,action,show,vbar";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "sb_vbar_clip_master";
+           }
+           program { name: "vbar_hide";
+               signal: "elm,action,hide,vbar";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "sb_vbar_clip_master";
+           }
+           program { name: "vbar_show_always";
+               signal: "elm,action,show_always,vbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbvis_v);
+                   v |= get_int(sbalways_v);
+                   if (!v) {
+                       set_int(sbalways_v, 1);
+                       emit("do-show-vbar", "");
+                       set_int(sbvis_v, 1);
+                   }
+               }
+           }
+           program { name: "vbar_show_notalways";
+               signal: "elm,action,show_notalways,vbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbalways_v);
+                   if (v) {
+                       set_int(sbalways_v, 0);
+                       v = get_int(sbvis_v);
+                       if (!v) {
+                           emit("do-hide-vbar", "");
+                           set_int(sbvis_v, 0);
+                       }
+                   }
+               }
+           }
+           program { name: "sb_vbar_show";
+               signal: "do-show-vbar";
+               source: "";
+               action:  STATE_SET "default" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_vbar_clip";
+           }
+           program { name: "sb_vbar_hide";
+               signal: "do-hide-vbar";
+               source: "";
+               action:  STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_vbar_clip";
+           }
+
+           program { name: "hbar_show";
+               signal: "elm,action,show,hbar";
+               source: "elm";
+               action:  STATE_SET "default" 0.0;
+               target: "sb_hbar_clip_master";
+           }
+           program { name: "hbar_hide";
+               signal: "elm,action,hide,hbar";
+               source: "elm";
+               action:  STATE_SET "hidden" 0.0;
+               target: "sb_hbar_clip_master";
+           }
+           program { name: "hbar_show_always";
+               signal: "elm,action,show_always,hbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbvis_h);
+                   v |= get_int(sbalways_h);
+                   if (!v) {
+                       set_int(sbalways_h, 1);
+                       emit("do-show-hbar", "");
+                       set_int(sbvis_h, 1);
+                   }
+               }
+           }
+           program { name: "hbar_show_notalways";
+               signal: "elm,action,show_notalways,hbar";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbalways_h);
+                   if (v) {
+                       set_int(sbalways_h, 0);
+                       v = get_int(sbvis_h);
+                       if (!v) {
+                           emit("do-hide-hbar", "");
+                           set_int(sbvis_h, 0);
+                       }
+                   }
+               }
+           }
+           program { name: "sb_hbar_show";
+               signal: "do-show-hbar";
+               source: "";
+               action:  STATE_SET "default" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_hbar_clip";
+           }
+           program { name: "sb_hbar_hide";
+               signal: "do-hide-hbar";
+               source: "";
+               action:  STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.5;
+               target: "sb_hbar_clip";
+           }
+
+           program { name: "scroll";
+               signal: "elm,action,scroll";
+               source: "elm";
+               script {
+                   new v;
+                   v = get_int(sbvis_v);
+                   v |= get_int(sbalways_v);
+                   if (!v) {
+                       emit("do-show-vbar", "");
+                       set_int(sbvis_v, 1);
+                   }
+                   v = get_int(sbvis_h);
+                   v |= get_int(sbalways_h);
+                   if (!v) {
+                       emit("do-show-hbar", "");
+                       set_int(sbvis_h, 1);
+                   }
+                   v = get_int(sbvis_timer);
+                   if (v > 0) cancel_timer(v);
+                   v = timer(1.0, "timer0", 0);
+                   set_int(sbvis_timer, v);
+               }
+           }
+           program { name: "go1";
+               signal: "elm,state,busy,start";
+               source: "elm";
+               action: STATE_SET "active" 0.0;
+               transition: SINUSOIDAL 1.0;
+               target:  "busy_clip";
+           }
+           program { name: "go2";
+               signal: "elm,state,busy,start";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: LINEAR 0.5;
+               target: "busy";
+               after:  "go2";
+           }
+           program { name: "stop1";
+               signal: "elm,state,busy,stop";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               transition: SINUSOIDAL 1.0;
+               target: "busy_clip";
+               after: "stop2";
+           }
+         program { name: "stop2";
+            action: ACTION_STOP;
+            target: "go2";
+         }
+      }
+   }
+   group { name: "elm/map/marker/radio/default";
+        data {
+            item: size_w 24;
+            item: size_h 24;
+            item: size_max_w 58;
+            item: size_max_h 58;
+        }
+        images {
+               image: "map_item.png" COMP;
+        }
+        parts {
+            part { name: "whole";
+                description { state: "default" 0.0;
+                }
+            }
+            part { name: "base";
+                ignore_flags: ON_HOLD;
+                description { state: "default" 0.0;
+                    image.normal: "map_item.png";
+                }
+            }
+            part { name: "elm.icon";
+                type: SWALLOW;
+                clip_to: "whole";
+                mouse_events:  0;
+                description { state: "default" 0.0;
+                    rel1.relative: 0.27 0.27;
+                    rel2.relative: 0.73 0.73;
+                }
+            }
+            part { name: "elm.text";
+                type:          TEXT;
+                effect:        SOFT_SHADOW;
+                mouse_events:  0;
+                scale: 1;
+                description { state: "default" 0.0;
+                    align:    0.5 0.5;
+                    color: 224 224 224 255;
+                    color3: 0 0 0 64;
+                    rel1.relative: 0.28 0.25;
+                    rel2.relative: 0.75 0.75;
+                    text {
+                        font:     "Sans,Edje-Vera";
+                        size:     10;
+                        min:      0 0;
+                        align:    0.5 0.5;
+                    }
+                }
+            }
+       }
+       programs {
+            program { name: "open";
+                signal: "mouse,clicked,1";
+                source: "base";
+                action: SIGNAL_EMIT "open" "elm";
+            }
+            program { name: "bringin";
+                signal: "mouse,down,1,double";
+                source: "base";
+                action: SIGNAL_EMIT "bringin" "elm";
+            }
+       }
+   }
+   group { name: "elm/map/marker/radio2/default";
+        data {
+            item: size_w 24;
+            item: size_h 24;
+            item: size_max_w 58;
+            item: size_max_h 58;
+        }
+        images {
+               image: "map_item_2.png" COMP;
+        }
+        parts {
+            part { name: "base";
+                ignore_flags: ON_HOLD;
+                description { state: "default" 0.0;
+                    image.normal: "map_item_2.png";
+                }
+            }
+            part { name: "elm.text";
+                type:          TEXT;
+                effect:        SOFT_SHADOW;
+                mouse_events:  0;
+                scale: 1;
+                description { state: "default" 0.0;
+                    align:    0.5 0.5;
+                    color: 224 224 224 255;
+                    color3: 0 0 0 64;
+                    rel1.relative: 0.28 0.25;
+                    rel2.relative: 0.75 0.75;
+                    text {
+                        font:     "Sans,Edje-Vera";
+                        size:     10;
+                        min:      0 0;
+                        align:    0.5 0.5;
+                    }
+                }
+            }
+       }
+       programs {
+            program { name: "open";
+                signal: "mouse,clicked,1";
+                source: "base";
+                action: SIGNAL_EMIT "open" "elm";
+            }
+            program { name: "bringin";
+                signal: "mouse,down,1,double";
+                source: "base";
+                action: SIGNAL_EMIT "bringin" "elm";
+            }
+       }
+   }
+   group { name: "elm/map/marker/empty/default";
+        data {
+            item: size_w 22;
+            item: size_h 22;
+            item: size_max_w 64;
+            item: size_max_h 64;
+        }
+        parts {
+            part { name: "whole";
+                description { state: "default" 0.0;
+                }
+            }
+            part { name: "base";
+                ignore_flags: ON_HOLD;
+                description { state: "default" 0.0;
+                }
+            }
+            part { name: "elm.icon";
+                type: SWALLOW;
+                clip_to: "whole";
+                mouse_events:  0;
+                description { state: "default" 0.0;
+                }
+            }
+            part { name: "elm.text";
+                type:          TEXT;
+                effect:        SOFT_SHADOW;
+                mouse_events:  0;
+                scale: 1;
+                description { state: "default" 0.0;
+                    align:    0.5 0.5;
+                    color: 224 224 224 255;
+                    color3: 0 0 0 64;
+                    rel1.relative: 0.28 0.25;
+                    rel2.relative: 0.75 0.75;
+                    text {
+                        font:     "Sans,Edje-Vera";
+                        size:     10;
+                        min:      0 0;
+                        align:    0.5 0.5;
+                    }
+                }
+            }
+       }
+       programs {
+            program { name: "open";
+                signal: "mouse,clicked,1";
+                source: "base";
+                action: SIGNAL_EMIT "open" "elm";
+            }
+            program { name: "bringin";
+                signal: "mouse,down,1,double";
+                source: "base";
+                action: SIGNAL_EMIT "bringin" "elm";
+            }
+       }
+   }
+   group { name: "elm/map/marker_bubble/default";
+    images {
+      image: "bubble.png" COMP;
+      image: "bubble_shine.png" COMP;
+    }
+    data {
+            item: size_w 400;
+            item: size_h 100;
+        }
+    parts {
+    part { name: "clipper";
+        mouse_events:  1;
+        description { state: "default" 0.0;
+          color: 255 255 255 0;
+        }
+        description { state: "show" 0.0;
+            inherit: "default" 0.0;
+            color: 255 255 255 255;
+        }
+      }
+     part { name: "base0";
+        mouse_events:  0;
+        clip_to: "clipper";
+        description { state: "default" 0.0;
+          image {
+            normal: "bubble.png";
+            border: 11 36 10 19;
+          }
+          image.middle: SOLID;
+          fill.smooth: 0;
+        }
+      }
+      part { name: "elm.swallow.content";
+        type: SWALLOW;
+        clip_to: "clipper";
+        description { state: "default" 0.0;
+            align: 0.5 0.5;
+          rel1 {
+            offset: 9 8;
+          }
+          rel2 {
+            offset: -10 -17;
+          }
+        }
+      }
+      part { name: "shine";
+        mouse_events:  0;
+        clip_to: "clipper";
+        description { state:    "default" 0.0;
+          rel1 {
+            to: "base0";
+          }
+          rel2 {
+            to: "base0";
+            relative: 1.0 0.5;
+          }
+          image {
+            normal: "bubble_shine.png";
+            border: 5 5 5 0;
+          }
+          fill.smooth: 0;
+        }
+        }
+    }
+    programs {
+        program { name: "show";
+            signal: "show";
+            action: STATE_SET "show" 0.0;
+            target: "clipper";
+            transition: ACCELERATE 0.5;
+        }
+    }
+  }
+
+/////////////////////////////////////////////////////////////////////////////
+// PANES
+/////////////////////////////////////////////////////////////////////////////
+  group {
+     name: "elm/panes/vertical/default";
+      images {
+        image: "bt_base1.png" COMP;
+        image: "bt_base2.png" COMP;
+        image: "bt_hilight.png" COMP;
+        image: "bt_shine.png" COMP;
+        image: "bt_glow.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+         image: "arrow_right.png" COMP;
+         image: "arrow_left.png" COMP;
+      }
+     parts
+       {
+          part
+            {
+               name: "whole";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    visible: 0;
+                 }
+            }
+
+         //2 contents
+          part
+            {
+               name: "whole_left";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel2.to_x: "elm.bar";
+                    rel2.relative: 0.0 1.0;
+                    visible: 1;
+                 }
+            }
+          part
+            {
+               name: "elm.swallow.left";
+               type: SWALLOW;
+               clip_to: "whole_left";
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "whole_left";
+                    rel2.to: "whole_left";
+                 }
+            }
+
+            part
+            {
+               name: "whole_right";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to_x: "elm.bar";
+                    rel1.relative: 1.0 0.0;
+                    visible: 1;
+                 }
+            }
+          part
+            {
+               name: "elm.swallow.right";
+               type: SWALLOW;
+               clip_to: "whole_right";
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "whole_right";
+                    rel2.to: "whole_right";
+                 }
+            }
+         //BAR
+        part { name: "elm.bar";
+           mouse_events: 1;
+            dragable {
+               confine: "whole";
+               x: 1 1 1;
+               y: 0 0 0;
+            }
+           description { state: "default" 0.0;
+               max: 15 9999;
+               min: 15 100;
+               rel1.relative: 0.0 0.5;
+               rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_base2.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "clicked" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "bt_base1.png";
+               image.middle: SOLID;
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+           }
+        }
+        part {   name: "over1";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+            rel1.to: "elm.bar";
+            rel2.to: "elm.bar";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_hilight.png";
+                 border: 7 7 7 0;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "over2";
+           mouse_events: 1;
+           repeat_events: 1;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+            rel1.to: "elm.bar";
+            rel2.to: "elm.bar";
+              image {
+                 normal: "bt_shine.png";
+                 border: 7 7 7 7;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              visible: 0;
+           }
+        }
+         part { name: "over3";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+            rel1.to: "elm.bar";
+            rel2.to: "elm.bar";
+               image {
+                  normal: "bt_glow.png";
+                  border: 12 12 12 12;
+               }
+              fill.smooth : 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit:  "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+
+         //Arrow
+         part {
+            name: "arrow_right";
+            description { state: "default" 0.0;
+                min: 45 45;
+                max: 45 45;
+                color: 255 255 255 0;
+
+                rel1.relative: 1.0 0.5;
+                rel1.to_x: "elm.bar";
+                rel1.offset: 45/2 -45/2;
+
+                rel2.relative: 1.0 0.5;
+                rel2.to_x: "elm.bar";
+                rel2.offset: 45/2 45/2;
+
+                image.normal: "arrow_right.png";
+
+                fixed: 1 1;
+            }
+            description { state: "anim_1" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 200;
+                rel1.offset: (45/2 + 10) -45/2;
+                rel2.offset: (45/2 +10) 45/2;
+            }
+            description { state: "anim_2" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 0;
+                rel1.offset: (45/2 + 20) -45/2;
+                rel2.offset: (45/2 + 20) 45/2;
+            }
+         }
+        part {
+            name: "arrow_left";
+            description { state: "default" 0.0;
+                min: 45 45;
+                max: 45 45;
+                color: 255 255 255 0;
+
+                rel1.relative: 0.0 0.5;
+                rel1.to_x: "elm.bar";
+                rel1.offset: -45/2 -45/2;
+
+                rel2.relative: 0.0 0.5;
+                rel2.to_x: "elm.bar";
+                rel2.offset: -45/2 45/2;
+
+                image.normal: "arrow_left.png";
+
+                fixed: 1 1;
+            }
+            description { state: "anim_1" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 200;
+                rel1.offset: (-45/2 - 10) -45/2;
+                rel2.offset: (-45/2 - 10) 45/2;
+            }
+            description { state: "anim_2" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 0;
+                rel1.offset: (-45/2 - 20) -45/2;
+                rel2.offset: (-45/2 - 20) 45/2;
+            }
+         }
+
+       }
+        programs {
+        program {
+           name:   "button_click";
+           signal: "mouse,down,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,press" "";
+           after: "button_click_anim";
+            after: "arrow_anim_start";
+        }
+        program {
+           name:   "button_click_anim";
+           action: STATE_SET "clicked" 0.0;
+           target: "elm.bar";
+        }
+        program {
+           name:   "button_unclick";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,unpress" "";
+           after: "button_unclick_anim";
+            after: "arrow_anim_stop";
+        }
+        program {
+           name:   "button_unclick_anim";
+           action: STATE_SET "default" 0.0;
+           target: "elm.bar";
+        }
+        program {
+           name:   "button_click2";
+           signal: "mouse,down,1";
+           source: "over3";
+           action: STATE_SET "clicked" 0.0;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick2";
+           signal: "mouse,up,1";
+           source: "over3";
+           action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.5;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick3";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,click" "";
+        }
+         program {
+           name:   "button_down_double";
+           signal: "mouse,down,1,double";
+           source: "over3";
+            action: SIGNAL_EMIT "elm,action,click,double" "";
+        }
+
+         //arrows animation
+         program {
+            name: "arrow_anim_start";
+            action: STATE_SET "anim_1" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            transition: LINEAR 0.6;
+            after: "arrow_anim_1";
+         }
+         program {
+            name: "arrow_anim_1";
+            action: STATE_SET "anim_2" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            transition: LINEAR 0.6;
+            after: "arrow_anim_2";
+         }
+         program {
+            name: "arrow_anim_2";
+            action: STATE_SET "default" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            after: "arrow_anim_start";
+         }
+         program {
+            name: "arrow_anim_stop";
+            action: ACTION_STOP;
+            target: "arrow_anim_start";
+            target: "arrow_anim_1";
+            target: "arrow_anim_2";
+            after: "arrow_anim_stop_1";
+         }
+         program {
+            name: "arrow_anim_stop_1";
+            action: STATE_SET "default" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            transition: DECELERATE 0.4;
+        }
+      }
+  }
+
+  group {
+     name: "elm/panes/horizontal/default";
+      images {
+        image: "bt_base1.png" COMP;
+        image: "bt_base2.png" COMP;
+        image: "bt_hilight.png" COMP;
+        image: "bt_shine.png" COMP;
+        image: "bt_glow.png" COMP;
+        image: "bt_dis_base.png" COMP;
+        image: "bt_dis_hilight.png" COMP;
+         image: "arrow_up.png" COMP;
+         image: "arrow_down.png" COMP;
+      }
+     parts
+       {
+          part
+            {
+               name: "whole";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    visible: 0;
+                 }
+            }
+
+         //2 contents
+          part
+            {
+               name: "whole_left";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel2.to_y: "elm.bar";
+                    rel2.relative: 1.0 0.0;
+                    visible: 1;
+                 }
+            }
+          part
+            {
+               name: "elm.swallow.left";
+               type: SWALLOW;
+               clip_to: "whole_left";
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "whole_left";
+                    rel2.to: "whole_left";
+                 }
+            }
+
+            part
+            {
+               name: "whole_right";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to_y: "elm.bar";
+                    rel1.relative: 0.0 1.0;
+                    visible: 1;
+                 }
+            }
+          part
+            {
+               name: "elm.swallow.right";
+               type: SWALLOW;
+               clip_to: "whole_right";
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "whole_right";
+                    rel2.to: "whole_right";
+                 }
+            }
+         //BAR
+        part { name: "elm.bar";
+           mouse_events: 1;
+            dragable {
+               confine: "whole";
+               x: 0 0 0;
+               y: 1 1 1;
+            }
+           description { state: "default" 0.0;
+               max: 999 15;
+               min: 100 15;
+               rel1.relative: 0.5 0.0;
+               rel2.relative: 0.5 1.0;
+              image {
+                 normal: "bt_base2.png";
+                 border: 7 7 7 7;
+              }
+               image.middle: SOLID;
+           }
+           description { state: "clicked" 0.0;
+              inherit: "default" 0.0;
+              image.normal: "bt_base1.png";
+               image.middle: SOLID;
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_base.png";
+                 border: 4 4 4 4;
+              }
+           }
+        }
+        part {   name: "over1";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+            rel1.to: "elm.bar";
+            rel2.to: "elm.bar";
+              rel2.relative: 1.0 0.5;
+              image {
+                 normal: "bt_hilight.png";
+                 border: 7 7 7 0;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              image {
+                 normal: "bt_dis_hilight.png";
+                 border: 4 4 4 0;
+              }
+           }
+        }
+        part { name: "over2";
+           mouse_events: 1;
+           repeat_events: 1;
+            ignore_flags: ON_HOLD;
+           description { state: "default" 0.0;
+            rel1.to: "elm.bar";
+            rel2.to: "elm.bar";
+              image {
+                 normal: "bt_shine.png";
+                 border: 7 7 7 7;
+              }
+           }
+           description { state: "disabled" 0.0;
+              inherit:  "default" 0.0;
+              visible: 0;
+           }
+        }
+         part { name: "over3";
+            mouse_events: 1;
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+            rel1.to: "elm.bar";
+            rel2.to: "elm.bar";
+               image {
+                  normal: "bt_glow.png";
+                  border: 12 12 12 12;
+               }
+              fill.smooth : 0;
+            }
+            description { state: "clicked" 0.0;
+               inherit:  "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+
+         //Arrow
+         part {
+            name: "arrow_right";
+            description { state: "default" 0.0;
+                min: 45 45;
+                max: 45 45;
+                color: 255 255 255 0;
+
+                rel1.relative: 0.5 1.0;
+                rel1.to_y: "elm.bar";
+                rel1.offset: -45/2 45/2;
+
+                rel2.relative: 0.5 1.0;
+                rel2.to_y: "elm.bar";
+                rel2.offset: 45/2 45/2;
+
+                image.normal: "arrow_down.png";
+
+                fixed: 1 1;
+            }
+            description { state: "anim_1" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 200;
+                rel1.offset: -45/2 (45/2 +10);
+                rel2.offset: 45/2 (45/2 +10);
+            }
+            description { state: "anim_2" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 0;
+                rel1.offset: -45/2 (45/2 + 20);
+                rel2.offset: 45/2 (45/2 + 20);
+            }
+         }
+        part {
+            name: "arrow_left";
+            description { state: "default" 0.0;
+                min: 45 45;
+                max: 45 45;
+                color: 255 255 255 0;
+
+                rel1.relative: 0.5 0.0;
+                rel1.to_y: "elm.bar";
+                rel1.offset: -45/2 -45/2;
+
+                rel2.relative: 0.5 0.0;
+                rel2.to_y: "elm.bar";
+                rel2.offset: 45/2 -45/2;
+
+                image.normal: "arrow_up.png";
+
+                fixed: 1 1;
+            }
+            description { state: "anim_1" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 200;
+                rel1.offset: -45/2 (-45/2 - 10);
+                rel2.offset: 45/2 (-45/2 - 10);
+            }
+            description { state: "anim_2" 0.0;
+                inherit: "default" 0.0;
+                color: 255 255 255 0;
+                rel1.offset: -45/2 (-45/2 - 20);
+                rel2.offset: 45/2 (-45/2 - 20);
+            }
+         }
+
+       }
+        programs {
+        program {
+           name:   "button_click";
+           signal: "mouse,down,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,press" "";
+           after: "button_click_anim";
+            after: "arrow_anim_start";
+        }
+        program {
+           name:   "button_click_anim";
+           action: STATE_SET "clicked" 0.0;
+           target: "elm.bar";
+        }
+        program {
+           name:   "button_unclick";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,unpress" "";
+           after: "button_unclick_anim";
+            after: "arrow_anim_stop";
+        }
+        program {
+           name:   "button_unclick_anim";
+           action: STATE_SET "default" 0.0;
+           target: "elm.bar";
+        }
+        program {
+           name:   "button_click2";
+           signal: "mouse,down,1";
+           source: "over3";
+           action: STATE_SET "clicked" 0.0;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick2";
+           signal: "mouse,up,1";
+           source: "over3";
+           action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.5;
+           target: "over3";
+        }
+        program {
+           name:   "button_unclick3";
+           signal: "mouse,up,1";
+           source: "over2";
+           action: SIGNAL_EMIT "elm,action,click" "";
+        }
+         program {
+           name:   "button_down_double";
+           signal: "mouse,down,1,double";
+           source: "over3";
+            action: SIGNAL_EMIT "elm,action,click,double" "";
+        }
+
+         //arrows animation
+         program {
+            name: "arrow_anim_start";
+            action: STATE_SET "anim_1" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            transition: LINEAR 0.6;
+            after: "arrow_anim_1";
+         }
+         program {
+            name: "arrow_anim_1";
+            action: STATE_SET "anim_2" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            transition: LINEAR 0.6;
+            after: "arrow_anim_2";
+         }
+         program {
+            name: "arrow_anim_2";
+            action: STATE_SET "default" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            after: "arrow_anim_start";
+         }
+         program {
+            name: "arrow_anim_stop";
+            action: ACTION_STOP;
+            target: "arrow_anim_start";
+            target: "arrow_anim_1";
+            target: "arrow_anim_2";
+            after: "arrow_anim_stop_1";
+         }
+         program {
+            name: "arrow_anim_stop_1";
+            action: STATE_SET "default" 0.0;
+            target: "arrow_right";
+            target: "arrow_left";
+            transition: DECELERATE 0.4;
+        }
+      }
+  }
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// PANEL
+/////////////////////////////////////////////////////////////////////////////
+  group {
+     name: "elm/panel/base/left";
+     alias: "elm/panel/base/top";
+     images
+       {
+          image: "bt_base1.png" COMP;
+          image: "bt_hilight.png" COMP;
+          image: "bt_shine.png" COMP;
+          image: "bt_glow.png" COMP;
+          image: "bt_dis_base.png" COMP;
+          image: "icon_arrow_left.png" COMP;
+          image: "icon_arrow_right.png" COMP;
+       }
+       data {
+          item: "focus_highlight" "on";
+       }
+     parts
+       {
+            part { name: "focus_highlight";
+               description { state: "default" 0.0;
+                  visible: 0;
+                  color: 255 255 255 0;
+                  rel1 {
+                     to: "btn";
+                     offset: -8 -8;
+                  }
+                  rel2 {
+                     to: "btn";
+                     offset: 7 7;
+                  }
+                  image {
+                     normal: "frame_2.png";
+                     border: 5 5 32 26;
+                     middle: 0;
+                  }
+               }
+               description { state: "enabled" 0.0;
+                  inherit: "default" 0.0;
+                  visible: 1;
+                  color: 255 255 255 255;
+               }
+            }
+          part
+            {
+               name: "bg";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    color: 255 255 255 0;
+                    rel1.relative: 0.0 0.0;
+                    rel1.offset: 0 0;
+                    rel2.relative: 1.0 1.0;
+                    rel2.offset: -1 -1;
+                 }
+               description
+                 {
+                    state: "hidden" 0.0;
+                    inherit: "default" 0.0;
+                    rel1.relative: -1.0 0.0;
+                    rel1.offset: 21 0;
+                    rel2.relative: 0.0 1.0;
+                    rel2.offset: 20 -1;
+                 }
+            }
+          part
+            {
+               name: "base";
+               type: IMAGE;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "bg";
+                    rel2.to: "bg";
+                    rel2.offset: -20 -1;
+                    image
+                      {
+                         normal: "bt_dis_base.png";
+                         border: 4 4 4 4;
+                      }
+                 }
+            }
+          part
+            {
+               name: "clipper";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1
+                      {
+                         offset: 4 4;
+                         to: "base";
+                      }
+                    rel2
+                      {
+                         offset: -5 -5;
+                         to: "base";
+                      }
+                 }
+            }
+          part
+            {
+               name: "elm.swallow.content";
+               type: SWALLOW;
+               clip_to: "clipper";
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "clipper";
+                    rel2.to: "clipper";
+                 }
+            }
+          part
+            {
+               name: "btn";
+               type: IMAGE;
+               mouse_events: 1;
+               description
+                 {
+                    state: "default" 0.0;
+                    max: 32 48;
+                    fixed: 1 1;
+                    align: 0.0 0.5;
+                    rel1
+                      {
+                         relative: 1.0 0.0;
+                         offset: -3 0;
+                         to_x: "base";
+                      }
+                    rel2.to_x: "bg";
+                    image
+                      {
+                         normal: "bt_base1.png";
+                         border: 0 5 4 12;
+                      }
+                    fill.smooth: 0;
+                 }
+               description
+                 {
+                    state: "clicked" 0.0;
+                    inherit: "default" 0.0;
+                 }
+            }
+          part
+            {
+               name: "btn_over";
+               type: IMAGE;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "btn";
+                    rel2
+                      {
+                         relative: 1.0 0.5;
+                         to: "btn";
+                      }
+                    image
+                      {
+                         normal: "bt_hilight.png";
+                         border: 0 7 7 0;
+                      }
+                 }
+            }
+          part
+            {
+               name: "btn_over2";
+               type: IMAGE;
+               mouse_events: 1;
+               repeat_events: 1;
+               ignore_flags: ON_HOLD;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "btn";
+                    rel2.to: "btn";
+                    image
+                      {
+                         normal: "bt_shine.png";
+                         border: 0 7 7 7;
+                    }
+                 }
+            }
+          part
+            {
+               name: "btn_over3";
+               type: IMAGE;
+               mouse_events: 1;
+               repeat_events: 1;
+               description
+                 {
+                    state: "default" 0.0;
+                    color: 255 255 255 0;
+                    rel1.to: "btn";
+                    rel2.to: "btn";
+                    image
+                      {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                    }
+                  fill.smooth: 0;
+               }
+             description
+               {
+                  state: "clicked" 0.0;
+                  inherit: "default" 0.0;
+                  visible: 1;
+                  color: 255 255 255 255;
+               }
+            }
+          part
+            {
+               name: "btn_icon";
+               type: IMAGE;
+               repeat_events: 1;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "btn";
+                    rel2.to: "btn";
+                    align: 0.5 0.5;
+                    min: 16 16;
+                    max: 16 16;
+                    image.normal: "icon_arrow_left.png";
+                 }
+               description
+                 {
+                    state: "hidden" 0.0;
+                    inherit: "default" 0.0;
+                    image.normal: "icon_arrow_right.png";
+                 }
+            }
+       }
+     programs
+       {
+          program
+            {
+               name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "bg";
+               target: "btn_icon";
+               transition: LINEAR 0.5;
+            }
+          program
+            {
+               name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "bg";
+               target: "btn_icon";
+               transition: LINEAR 0.5;
+            }
+          program
+            {
+               name: "btn_click";
+               signal: "mouse,down,1";
+               source: "btn_over2";
+               action: STATE_SET "clicked" 0.0;
+               target: "btn";
+            }
+          program
+            {
+               name: "btn_unclick";
+               signal: "mouse,up,1";
+               source: "btn_over2";
+               action: STATE_SET "default" 0.0;
+               target: "btn";
+            }
+          program
+            {
+               name: "btn_click2";
+               signal: "mouse,down,1";
+               source: "btn_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "btn_over3";
+            }
+          program
+            {
+               name: "btn_unclick2";
+               signal: "mouse,up,1";
+               source: "btn_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "btn_over3";
+            }
+          program
+            {
+               name: "btn_unclick3";
+               signal: "mouse,clicked,1";
+               source: "btn_over2";
+               action: SIGNAL_EMIT "elm,action,panel,toggle" "";
+            }
+         program { name: "highlight_show";
+            signal: "elm,action,focus_highlight,show";
+            source: "elm";
+            action: STATE_SET "enabled" 0.0;
+            transition: ACCELERATE 0.3;
+            target: "focus_highlight";
+         }
+         program { name: "highlight_hide";
+            signal: "elm,action,focus_highlight,hide";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.3;
+            target: "focus_highlight";
+         }
+       }
+  }
+
+  group {
+     name: "elm/panel/base/right";
+     alias: "elm/panel/base/bottom";
+     images
+       {
+          image: "bt_base1.png" COMP;
+          image: "bt_hilight.png" COMP;
+          image: "bt_shine.png" COMP;
+          image: "bt_glow.png" COMP;
+          image: "bt_dis_base.png" COMP;
+          image: "icon_arrow_left.png" COMP;
+          image: "icon_arrow_right.png" COMP;
+       }
+     parts
+       {
+            part { name: "focus_highlight";
+               description { state: "default" 0.0;
+                  visible: 0;
+                  color: 255 255 255 0;
+                  rel1 {
+                     to: "btn";
+                     offset: -8 -8;
+                  }
+                  rel2 {
+                     to: "btn";
+                     offset: 7 7;
+                  }
+                  image {
+                     normal: "frame_2.png";
+                     border: 5 5 32 26;
+                     middle: 0;
+                  }
+               }
+               description { state: "enabled" 0.0;
+                  inherit: "default" 0.0;
+                  visible: 1;
+                  color: 255 255 255 255;
+               }
+            }
+          part
+            {
+               name: "bg";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    color: 255 255 255 0;
+                    rel1.relative: 0.0 0.0;
+                    rel1.offset: 0 0;
+                    rel2.relative: 1.0 1.0;
+                    rel2.offset: -1 -1;
+                 }
+               description
+                 {
+                    state: "hidden" 0.0;
+                    inherit: "default" 0.0;
+                    rel1.relative: 1.0 0.0;
+                    rel1.offset: -22 0;
+                    rel2.relative: 2.0 1.0;
+                    rel2.offset: -23 -1;
+                 }
+            }
+          part
+            {
+               name: "base";
+               type: IMAGE;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "bg";
+                    rel1.offset: 20 0;
+                    rel2.to: "bg";
+                    image
+                      {
+                         normal: "bt_dis_base.png";
+                         border: 4 4 4 4;
+                      }
+                 }
+            }
+          part
+            {
+               name: "clipper";
+               type: RECT;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1
+                      {
+                         offset: 4 4;
+                         to: "base";
+                      }
+                    rel2
+                      {
+                         offset: -5 -5;
+                         to: "base";
+                      }
+                 }
+            }
+          part
+            {
+               name: "elm.swallow.content";
+               type: SWALLOW;
+               clip_to: "clipper";
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "clipper";
+                    rel2.to: "clipper";
+                 }
+            }
+          part
+            {
+               name: "btn";
+               type: IMAGE;
+               mouse_events: 1;
+               description
+                 {
+                    state: "default" 0.0;
+                    max: 32 48;
+                    fixed: 1 1;
+                    align: 1 0.5;
+                    rel1
+                      {
+                         to_x: "bg";
+                      }
+                    rel2
+                      {
+                         offset: 2 0;
+                         relative: 0.0 1;
+                         to_x: "base";
+                      }
+                    image
+                      {
+                         normal: "bt_base1.png";
+                         border: 5 0 4 12;
+                      }
+                    fill.smooth: 0;
+                 }
+               description
+                 {
+                    state: "clicked" 0.0;
+                    inherit: "default" 0.0;
+                 }
+            }
+          part
+            {
+               name: "btn_over";
+               type: IMAGE;
+               mouse_events: 0;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "btn";
+                    rel2
+                      {
+                         relative: 1.0 0.5;
+                         to: "btn";
+                      }
+                    image
+                      {
+                         normal: "bt_hilight.png";
+                         border: 7 0 7 0;
+                      }
+                 }
+            }
+          part
+            {
+               name: "btn_over2";
+               type: IMAGE;
+               mouse_events: 1;
+               repeat_events: 1;
+               ignore_flags: ON_HOLD;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "btn";
+                    rel2.to: "btn";
+                    image
+                      {
+                         normal: "bt_shine.png";
+                         border: 7 0 7 7;
+                    }
+                 }
+            }
+          part
+            {
+               name: "btn_over3";
+               type: IMAGE;
+               mouse_events: 1;
+               repeat_events: 1;
+               description
+                 {
+                    state: "default" 0.0;
+                    color: 255 255 255 0;
+                    rel1.to: "btn";
+                    rel2.to: "btn";
+                    image
+                      {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                    }
+                  fill.smooth: 0;
+               }
+             description
+               {
+                  state: "clicked" 0.0;
+                  inherit: "default" 0.0;
+                  visible: 1;
+                  color: 255 255 255 255;
+               }
+            }
+          part
+            {
+               name: "btn_icon";
+               type: IMAGE;
+               repeat_events: 1;
+               description
+                 {
+                    state: "default" 0.0;
+                    rel1.to: "btn";
+                    rel2.to: "btn";
+                    align: 0.5 0.5;
+                    min: 16 16;
+                    max: 16 16;
+                    image.normal: "icon_arrow_right.png";
+                 }
+               description
+                 {
+                    state: "hidden" 0.0;
+                    inherit: "default" 0.0;
+                    image.normal: "icon_arrow_left.png";
+                 }
+            }
+       }
+     programs
+       {
+          program
+            {
+               name: "show";
+               signal: "elm,action,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "bg";
+               target: "btn_icon";
+               transition: LINEAR 0.5;
+            }
+          program
+            {
+               name: "hide";
+               signal: "elm,action,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "bg";
+               target: "btn_icon";
+               transition: LINEAR 0.5;
+            }
+          program
+            {
+               name: "btn_click";
+               signal: "mouse,down,1";
+               source: "btn_over2";
+               action: STATE_SET "clicked" 0.0;
+               target: "btn";
+            }
+          program
+            {
+               name: "btn_unclick";
+               signal: "mouse,up,1";
+               source: "btn_over2";
+               action: STATE_SET "default" 0.0;
+               target: "btn";
+            }
+          program
+            {
+               name: "btn_click2";
+               signal: "mouse,down,1";
+               source: "btn_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "btn_over3";
+            }
+          program
+            {
+               name: "btn_unclick2";
+               signal: "mouse,up,1";
+               source: "btn_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "btn_over3";
+            }
+          program
+            {
+               name: "btn_unclick3";
+               signal: "mouse,up,1";
+               source: "btn_over2";
+               action: SIGNAL_EMIT "elm,action,panel,toggle" "";
+            }
+         program { name: "highlight_show";
+            signal: "elm,action,focus";
+            source: "elm";
+            action: STATE_SET "enabled" 0.0;
+            transition: ACCELERATE 0.3;
+            target: "focus_highlight";
+         }
+         program { name: "highlight_hide";
+            signal: "elm,action,unfocus";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            transition: DECELERATE 0.3;
+            target: "focus_highlight";
+         }
+       }
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+  group { name: "elm/conformant/base/default";
+     parts {
+        part { name: "elm.swallow.shelf";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              align: 0.0 0.0;
+              rel2.relative: 1.0 0.0;
+           }
+        }
+        part { name: "elm.swallow.content";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              align: 0.5 0.5;
+              rel1.relative: 0.0 1.0;
+              rel1.to_y: "elm.swallow.shelf";
+              rel2.relative: 1.0 0.0;
+              rel2.to_y: "elm.swallow.panel";
+           }
+        }
+        part { name: "elm.swallow.panel";
+           type: SWALLOW;
+           description { state: "default" 0.0;
+              fixed: 1 1;
+              align: 0.0 1.0;
+              rel1.relative: 0.0 1.0;
+           }
+        }
+     }
+  }
+
+/////////////////////////////////////////////////////////////////////////////
+// CALENDAR
+/////////////////////////////////////////////////////////////////////////////
+#define CH(_pos) \
+        part { name: "ch_"#_pos".base"; \
+           type: RECT; \
+           description { state: "default" 0.0; \
+              rel1 { \
+                 relative: (_pos % 7 * 7 / 8 / 6) 0; \
+                 to: "header"; \
+              } \
+              rel2 { \
+                 relative: (_pos % 7 * 7 / 8 / 6 + 1 / 8) 1; \
+                 to: "header"; \
+              } \
+               color: 0 0 0 0; \
+               visible: 0; \
+           } \
+        } \
+         part { name: "ch_"#_pos".text"; \
+            type: TEXT; \
+            effect: SOFT_SHADOW; \
+            mouse_events: 0; \
+            scale: 1; \
+           clip_to: "ch_"#_pos".clipper"; \
+            description { \
+               state: "default" 0.0; \
+               rel1.to: "ch_"#_pos".base"; \
+               rel2.to: "ch_"#_pos".base"; \
+               color: 0 0 0 255; \
+               color3: 0 0 0 0; \
+               text { \
+                  font: "Sans"; \
+                  size: 10; \
+                  min: 1 1; \
+                  align: 0.5 0.5; \
+               } \
+            } \
+        } \
+        part { name: "ch_"#_pos".clipper"; \
+           type: RECT; \
+           description { state: "default" 0.0; \
+              rel1.to: "ch_"#_pos".base"; \
+              rel2.to: "ch_"#_pos".base"; \
+           } \
+        }
+
+#define CIT(_pos) \
+        part { name: "cit_"#_pos".rect"; \
+           type: RECT; \
+           description { state: "default" 0.0; \
+              rel1 { \
+                 relative: (_pos % 7 * 7 / 8 / 6) \
+                           (_pos / 8 / 5 - _pos % 7 / 8 / 5); \
+                 to: "base"; \
+              } \
+              rel2 { \
+                 relative: (_pos % 7 * 7 / 8 / 6 + 1 / 8) \
+                           (_pos / 8 / 5 - _pos % 7 / 8 / 5 + 1 / 8); \
+                 to: "base"; \
+              } \
+               color: 0 0 0 0; \
+               visible: 0; \
+           } \
+        } \
+         part { \
+            name: "cit_"#_pos".event"; \
+            type: RECT; \
+            repeat_events: 1; \
+            description { \
+               rel1.to: "cit_"#_pos".rect"; \
+               rel2.to: "cit_"#_pos".rect"; \
+               state: "default" 0.0; \
+               color: 0 0 0 0; \
+            } \
+         } \
+         part { name: "cit_"#_pos".shelf"; \
+           type: RECT; \
+           mouse_events: 0; \
+           description { state: "default" 0.0; \
+               rel1 { \
+                  to: "cit_"#_pos".bg"; \
+                  offset: -1 -1; \
+               } \
+               rel2 { \
+                  to: "cit_"#_pos".bg"; \
+               } \
+               color: 200 200 200 255; \
+           } \
+        } \
+         part { name: "cit_"#_pos".hd"; \
+           type: RECT; \
+           mouse_events: 0; \
+           description { state: "default" 0.0; \
+               rel1 { \
+                  to: "cit_"#_pos".bg"; \
+                  offset: -1 -1; \
+               } \
+               rel2 { \
+                  to: "cit_"#_pos".bg"; \
+               } \
+               visible: 0; \
+               color: 160 0 0 255; \
+           } \
+           description { state: "visible" 0.0; \
+               inherit: "default" 0.0; \
+               visible: 1; \
+            } \
+        } \
+         part { \
+            name: "cit_"#_pos".base_sh"; \
+            mouse_events: 0; \
+            description { \
+               state: "default" 0.0; \
+               align: 0.0 0.0; \
+               min: 0 1; \
+               rel1 { \
+                  to: "cit_"#_pos".base"; \
+                  relative: 0.0 1.0; \
+                  offset: 0 0; \
+               } \
+               rel2 { \
+                  to: "cit_"#_pos".base"; \
+                  relative: 1.0 1.05; \
+                  offset: -1 0; \
+               } \
+               image { \
+                  normal: "ilist_item_shadow.png"; \
+               } \
+               fill.smooth: 0; \
+            } \
+         } \
+         part { \
+            name: "cit_"#_pos".base"; \
+            mouse_events: 0; \
+            description { \
+               state: "default" 0.0; \
+               rel1.to: "cit_"#_pos".rect"; \
+               rel2.to: "cit_"#_pos".rect"; \
+               rel2.offset: -1 -1; \
+               image { \
+                  normal: "ilist_1.png"; \
+                  border: 2 2 2 2; \
+               } \
+               fill.smooth: 0; \
+            } \
+            description { \
+               state: "today" 0.0; \
+               inherit: "default" 0.0; \
+               image.normal: "ilist_2.png"; \
+               color: 240 240 240 255; \
+            } \
+         } \
+         part { name: "cit_"#_pos".bg"; \
+            mouse_events: 0; \
+            description { state: "default" 0.0; \
+               visible: 0; \
+               color: 255 255 255 0; \
+               rel1 { \
+                  to: "cit_"#_pos".rect"; \
+                  relative: 0.0 0.0; \
+               } \
+               rel2 { \
+                  to: "cit_"#_pos".rect"; \
+                  relative: 1.0 1.0; \
+                  offset: -1 -1; \
+               } \
+               image { \
+                  normal: "bt_sm_base1.png"; \
+                  border: 6 6 6 6; \
+               } \
+               image.middle: SOLID; \
+            } \
+            description { state: "selected" 0.0; \
+               inherit: "default" 0.0; \
+               visible: 1; \
+               color: 255 255 255 255; \
+            } \
+         } \
+         part { name: "cit_"#_pos".text"; \
+            type: TEXT; \
+            effect: SOFT_SHADOW; \
+            mouse_events: 0; \
+            scale: 1; \
+            description { \
+               state: "default" 0.0; \
+               rel1.to: "cit_"#_pos".bg"; \
+               rel2.to: "cit_"#_pos".bg"; \
+               color: 0 0 0 255; \
+               color3: 0 0 0 0; \
+               text { \
+                  font: "Sans"; \
+                  size: 10; \
+                  min: 1 1; \
+                  align: 0.5 0.5; \
+               } \
+            } \
+            description { state: "selected" 0.0; \
+               inherit: "default" 0.0; \
+               color: 224 224 224 255; \
+               color3: 0 0 0 64; \
+            } \
+         } \
+         part { name: "cit_"#_pos".fg1"; \
+            mouse_events: 0; \
+            description { state: "default" 0.0; \
+               visible: 0; \
+               color: 255 255 255 0; \
+               rel1.to: "cit_"#_pos".bg"; \
+               rel2.relative: 1.0 0.5; \
+               rel2.to: "cit_"#_pos".bg"; \
+               image { \
+                  normal: "bt_sm_hilight.png"; \
+                  border: 6 6 6 0; \
+               } \
+            } \
+            description { state: "selected" 0.0; \
+               inherit: "default" 0.0; \
+               visible: 1; \
+               color: 255 255 255 255; \
+            } \
+         } \
+         part { name: "cit_"#_pos".fg2"; \
+            mouse_events: 0; \
+            description { state: "default" 0.0; \
+               visible: 0; \
+               color: 255 255 255 0; \
+               rel1.to: "cit_"#_pos".bg"; \
+               rel2.to: "cit_"#_pos".bg"; \
+               image { \
+                  normal: "bt_sm_shine.png"; \
+                  border: 6 6 6 0; \
+               } \
+            } \
+            description { state: "selected" 0.0; \
+               inherit: "default" 0.0; \
+               visible: 1; \
+               color: 255 255 255 255; \
+            } \
+         } \
+         part { name: "cit_"#_pos".check"; \
+           mouse_events: 0; \
+           description { state: "default" 0.0; \
+               rel1 { \
+                  to: "cit_"#_pos".bg"; \
+                  relative: 0.7 0.6; \
+                  offset: 1 1; \
+               } \
+               rel2 { \
+                  to: "cit_"#_pos".bg"; \
+                  relative: 1.1 1.2; \
+                  offset: -2 -2; \
+               } \
+               aspect: 1 1; \
+               visible: 0; \
+               color: 255 0 0 255; \
+               image.normal: "check.png"; \
+           } \
+           description { state: "visible" 0.0; \
+               inherit: "default" 0.0; \
+               visible: 1; \
+            } \
+        } \
+      programs { \
+         program { \
+            name:    "cit_"#_pos".go_active"; \
+            signal:  "cit_"#_pos",selected"; \
+            source:  "elm"; \
+            action:  STATE_SET "selected" 0.0; \
+            target:  "cit_"#_pos".bg"; \
+            target:  "cit_"#_pos".fg1"; \
+            target:  "cit_"#_pos".fg2"; \
+            target:  "cit_"#_pos".text"; \
+         } \
+         program { \
+            name:    "cit_"#_pos".go_passive"; \
+            signal:  "cit_"#_pos",unselected"; \
+            source:  "elm"; \
+            action:  STATE_SET "default" 0.0; \
+            target:  "cit_"#_pos".bg"; \
+            target:  "cit_"#_pos".fg1"; \
+            target:  "cit_"#_pos".fg2"; \
+            target:  "cit_"#_pos".text"; \
+         } \
+         program { \
+            name:    "cit_"#_pos".is_today"; \
+            signal:  "cit_"#_pos",today"; \
+            source:  "elm"; \
+            action:  STATE_SET "today" 0.0; \
+            target: "cit_"#_pos".base"; \
+         } \
+         program { \
+            name:    "cit_"#_pos".not_today"; \
+            signal:  "cit_"#_pos",not_today"; \
+            source:  "elm"; \
+            action:  STATE_SET "default" 0.0; \
+            target: "cit_"#_pos".base"; \
+         } \
+         program { \
+            source: "cit_"#_pos".clicked"; \
+            signal: "mouse,clicked,1"; \
+            source: "cit_"#_pos".event"; \
+           action: SIGNAL_EMIT "elm,action,selected" #_pos; \
+         } \
+         program { \
+            name:    "cit_"#_pos".clear"; \
+            signal:  "cit_"#_pos",clear"; \
+            source:  "elm"; \
+            action:  STATE_SET "default" 0.0; \
+            target: "cit_"#_pos".check"; \
+            target: "cit_"#_pos".hd"; \
+         } \
+         program { \
+            name:    "cit_"#_pos".checked"; \
+            signal:  "cit_"#_pos",checked"; \
+            source:  "elm"; \
+            action:  STATE_SET "visible" 0.0; \
+            target: "cit_"#_pos".check"; \
+         } \
+         program { \
+            name:    "cit_"#_pos".holiday"; \
+            signal:  "cit_"#_pos",holiday"; \
+            source:  "elm"; \
+            action:  STATE_SET "visible" 0.0; \
+            target: "cit_"#_pos".hd"; \
+         } \
+      }
+
+   group { name: "elm/calendar/base/default";
+       images {
+           image: "shelf_inset.png" COMP;
+           image: "bt_base1.png" COMP;
+           image: "bt_hilight.png" COMP;
+           image: "bt_shine.png" COMP;
+           image: "bt_glow.png" COMP;
+           image: "bt_dis_base.png" COMP;
+           image: "bt_dis_hilight.png" COMP;
+           image: "sp_bt_l.png" COMP;
+           image: "sp_bt_r.png" COMP;
+           image: "bt_sm_base1.png" COMP;
+           image: "bt_sm_shine.png" COMP;
+           image: "bt_sm_hilight.png" COMP;
+           image: "ilist_1.png" COMP;
+           image: "ilist_2.png" COMP;
+           image: "ilist_item_shadow.png" COMP;
+           image: "check.png" COMP;
+       }
+       parts {
+           part { name: "bg";
+               type: RECT;
+               description { state: "default" 0.0;
+                   min: 0 30;
+                   rel1.offset: 1 1;
+                   rel2.offset: -2 -2;
+                   color: 255 255 255 0;
+                   align: 0.0 0.5;
+               }
+           }
+           part { name: "spinner-base";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   min: 24 24;
+                   max: 999999 24;
+                   rel1.to: "bg";
+                  rel1.offset: 6 6;
+                   rel2.to: "bg";
+                  rel2.offset: -7 -7;
+                   color: 255 255 255 0;
+                   align: 0.0 0.0;
+               }
+           }
+           part { name: "conf_over_spinner";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   rel1.to: "spinner-base";
+                  rel1.offset: -3 -3;
+                   rel2.to: "spinner-base";
+                  rel2.offset: 2 2;
+                   image {
+                       normal: "shelf_inset.png";
+                       border: 7 7 7 7;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "table-base";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   min: 256 220;
+                   rel1.to_x: "bg";
+                   rel1.to_y: "spinner-base";
+                  rel1.offset: 6 6;
+                  rel1.relative: 0 1;
+                   rel2.to: "bg";
+                  rel2.offset: -7 -7;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "conf_over_table";
+               mouse_events:  0;
+               description { state: "default" 0.0;
+                   rel1.to: "table-base";
+                  rel1.offset: -3 -3;
+                   rel2.to: "table-base";
+                  rel2.offset: 2 2;
+                   image {
+                       normal: "shelf_inset.png";
+                       border: 7 7 7 7;
+                       middle: 0;
+                   }
+                   fill.smooth : 0;
+               }
+           }
+           part { name: "header";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "table-base";
+                  rel1.relative: 0 0;
+                   rel2.to: "table-base";
+                  rel2.relative: 1 0.1;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "base";
+               type: RECT;
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to_x: "table-base";
+                   rel1.to_y: "header";
+                  rel1.relative: 0 1;
+                  rel1.offset: 3 0;
+                   rel2.to: "table-base";
+                  rel2.offset: -3 0;
+                   color: 255 255 255 0;
+               }
+           }
+           part { name: "left_bt";
+               mouse_events:  1;
+               description { state: "default" 0.0;
+                   rel1 { to: "spinner-base";
+                       offset: 2 2;
+                   }
+                   rel2 { to: "spinner-base";
+                       offset: -3 -3;
+                   }
+                   align: 0.0 0.5;
+                   min: 24 24;
+                   max: 24 24;
+                   fixed: 1 1;
+                   image {
+                       normal: "bt_base1.png";
+                       border: 6 6 6 6;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "bt_base1.png";
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "left_over1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "left_bt";
+                   rel2 { to: "left_bt";
+                       relative: 1.0 0.5;
+                   }
+                   image {
+                       normal: "bt_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+           }
+           part { name: "left_over2";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "left_bt";
+                   rel2.to: "left_bt";
+                   image {
+                       normal: "bt_shine.png";
+                       border: 7 7 7 7;
+                   }
+               }
+           }
+           part { name: "left_over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "left_bt";
+                   rel2.to: "left_bt";
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "right_bt";
+               mouse_events:  1;
+               description { state: "default" 0.0;
+                   rel1 { to: "spinner-base";
+                       offset: -27 3;
+                   }
+                   rel2 { to: "spinner-base";
+                       offset: -3 -3;
+                   }
+                   align: 1.0 0.5;
+                   min: 24 24;
+                   max: 24 24;
+                   fixed: 1 1;
+                   image {
+                       normal: "bt_base1.png";
+                       border: 5 5 4 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit: "default" 0.0;
+                   image.normal: "bt_base1.png";
+                   image.middle: SOLID;
+               }
+           }
+           part { name: "right_over1";
+               mouse_events: 0;
+               description { state: "default" 0.0;
+                   rel1.to: "right_bt";
+                   rel2 { to: "right_bt";
+                       relative: 1.0 0.5;
+                   }
+                   image {
+                       normal: "bt_hilight.png";
+                       border: 7 7 7 0;
+                   }
+               }
+           }
+           part { name: "right_over2";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "right_bt";
+                   rel2.to: "right_bt";
+                   image {
+                       normal: "bt_shine.png";
+                       border: 7 7 7 7;
+                   }
+               }
+           }
+           part { name: "right_over3";
+               mouse_events: 1;
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   color: 255 255 255 0;
+                   rel1.to: "right_bt";
+                   rel2.to: "right_bt";
+                   image {
+                       normal: "bt_glow.png";
+                       border: 12 12 12 12;
+                   }
+                   fill.smooth : 0;
+               }
+               description { state: "clicked" 0.0;
+                   inherit:  "default" 0.0;
+                   visible: 1;
+                   color: 255 255 255 255;
+               }
+           }
+           part { name: "left_bt_icon";
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "left_bt";
+                   rel2.to: "left_bt";
+                   align: 0.5 0.5;
+                   min: 16 16;
+                   max: 16 16;
+                   image.normal: "sp_bt_l.png";
+               }
+           }
+           part { name: "right_bt_icon";
+               repeat_events: 1;
+               description { state: "default" 0.0;
+                   rel1.to: "right_bt";
+                   rel2.to: "right_bt";
+                   align: 0.5 0.5;
+                   min: 16 16;
+                   max: 16 16;
+                   image.normal: "sp_bt_r.png";
+               }
+           }
+           part { name: "month_text";
+               type: TEXT;
+               mouse_events: 0;
+               scale: 1;
+               description { state: "default" 0.0;
+                   align: 0 0.5;
+                   fixed: 1 1;
+                   rel1 { relative: 1.0 0.0;
+                       offset: 3 2;
+                       to: "left_bt";
+                       to_y: "spinner-base";
+                   }
+                   rel2 { relative: 0.0 1.0;
+                       offset: -3 -2;
+                       to_x: "right_bt";
+                       to_y: "spinner-base";
+                   }
+                   color: 0 0 0 255;
+                   text {
+                       font: "Sans,Edje-Vera";
+                       size: 12;
+                       min: 1 1;
+                       align: 0.5 0.5;
+                   }
+               }
+           }
+          CH(0)   CH(1)   CH(2)   CH(3)   CH(4)   CH(5)   CH(6)
+          CIT(0)  CIT(1)  CIT(2)  CIT(3)  CIT(4)  CIT(5)  CIT(6)
+          CIT(7)  CIT(8)  CIT(9)  CIT(10) CIT(11) CIT(12) CIT(13)
+          CIT(14) CIT(15) CIT(16) CIT(17) CIT(18) CIT(19) CIT(20)
+          CIT(21) CIT(22) CIT(23) CIT(24) CIT(25) CIT(26) CIT(27)
+          CIT(28) CIT(29) CIT(30) CIT(31) CIT(32) CIT(33) CIT(34)
+          CIT(35) CIT(36) CIT(37) CIT(38) CIT(39) CIT(40) CIT(41)
+       }
+       programs {
+           program { name: "dec_start";
+               signal: "mouse,down,1";
+               source: "left_bt";
+               action: SIGNAL_EMIT "elm,action,decrement,start" "";
+           }
+           program { name: "dec_stop";
+               signal: "mouse,up,1";
+               source: "left_bt";
+               action: SIGNAL_EMIT "elm,action,stop" "";
+           }
+           program { name: "inc_start";
+               signal: "mouse,down,1";
+               source: "right_bt";
+               action: SIGNAL_EMIT "elm,action,increment,start" "";
+           }
+           program { name: "inc_stop";
+               signal: "mouse,up,1";
+               source: "right_bt";
+               action: SIGNAL_EMIT "elm,action,stop" "";
+           }
+           program {
+               name:   "left_bt_click";
+               signal: "mouse,down,1";
+               source: "left_over2";
+               action: STATE_SET "clicked" 0.0;
+               target: "left_bt";
+           }
+           program {
+               name:   "left_bt_unclick";
+               signal: "mouse,up,1";
+               source: "left_over2";
+               action: STATE_SET "default" 0.0;
+               target: "left_bt";
+           }
+           program {
+               name:   "left_bt_click2";
+               signal: "mouse,down,1";
+               source: "left_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "left_over3";
+           }
+           program {
+               name:   "left_bt_unclick2";
+               signal: "mouse,up,1";
+               source: "left_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "left_over3";
+           }
+           program {
+               name:   "right_bt_click";
+               signal: "mouse,down,1";
+               source: "right_over2";
+               action: STATE_SET "clicked" 0.0;
+               target: "right_bt";
+           }
+           program {
+               name:   "right_bt_unclick";
+               signal: "mouse,up,1";
+               source: "right_over2";
+               action: STATE_SET "default" 0.0;
+               target: "right_bt";
+           }
+           program {
+               name:   "right_bt_click2";
+               signal: "mouse,down,1";
+               source: "right_over3";
+               action: STATE_SET "clicked" 0.0;
+               target: "right_over3";
+           }
+           program {
+               name:   "right_bt_unclick2";
+               signal: "mouse,up,1";
+               source: "right_over3";
+               action: STATE_SET "default" 0.0;
+               transition: DECELERATE 0.5;
+               target: "right_over3";
+           }
+       }
+   }
+
+#undef CIT
+#undef CH
+
+////////////////////////////////////////////////////////////////////////////////
+// colorselector
+////////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/colorselector/bg/default";
+      parts {
+         part { name: "elm.colorbar_0";
+            type: SWALLOW;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 120 30;
+               rel1.relative: 0.0 0.00653594771;
+               rel2.relative: 1.0 0.254901961;
+            }
+         }
+         part { name: "elm.colorbar_1";
+            type: SWALLOW;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 120 30;
+               rel1.relative: 0.0 0.254901961;
+               rel2.relative: 1.0 0.503267974;
+            }
+         }
+         part { name: "elm.colorbar_2";
+            type: SWALLOW;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 120 30;
+               rel1.relative: 0.0 0.503267974;
+               rel2.relative: 1.0 0.751633987;
+            }
+         }
+         part { name: "elm.colorbar_3";
+            type: SWALLOW;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 120 30;
+               rel1.relative: 0.0 0.751633987;
+               rel2.relative: 1.0 1.0;
+            }
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/base/default";
+      parts {
+         part { name: "elm.bar_bg";
+            type: SWALLOW;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               min: 60 22;
+               rel1 {
+                  relative: 0.0 0.8;
+                  to_x: "elm.arrow_bg";
+                  to_y: "elm.arrow_icon";
+                  offset: 0 0;
+               }
+               rel2 {
+                  relative: 1.0 0.83;
+                  to_x: "elm.arrow_bg";
+                  offset: 0 0;
+               }
+            }
+         }
+         part { name: "elm.bar";
+            type: SWALLOW;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "elm.bar_bg";
+               rel2.to: "elm.bar_bg";
+            }
+         }
+         part { name: "elm.arrow_bg";
+            type: SWALLOW;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  relative: 1.0 0.17;
+                  offset: 3 0;
+                  to_x: "elm.l_button";
+               }
+               rel2 {
+                  relative: 0.0 0.83;
+                     offset: -4 0;
+                  to_x: "elm.r_button";
+               }
+            }
+         }
+         part { name: "elm.arrow";
+            type: RECT;
+            mouse_events: 1;
+            scale: 1;
+            description { state: "default" 0.0;
+               min: 1 1;
+               fixed: 1 1;
+               align: 0 0;
+               rel1 {
+                  to_x: "elm.arrow_bg";
+               }
+               rel2 {
+                  relative: 0.0 0.17;
+                  to_x: "elm.arrow_bg";
+               }
+               color: 0 0 0 0;
+               visible: 0;
+            }
+            dragable {
+               confine: "elm.arrow_bg";
+               x: 1 1 0;
+               y: 0 0 0;
+            }
+         }
+         part { name: "elm.arrow_icon";
+            type: SWALLOW;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               min: 25 15;
+               max: 25 15;
+               fixed: 1 1;
+               align: 0.5 0;
+               rel1 {
+                  to_x: "elm.arrow";
+               }
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: 0 10;
+                  to_x: "elm.arrow";
+               }
+            }
+         }
+         part { name: "event";
+            type: RECT;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  to: "elm.arrow_icon";
+               }
+               rel2 {
+                  to_x: "elm.arrow_icon";
+                  to_y: "elm.arrow_bg";
+                  offset: 0 0;
+               }
+               color: 0 0 0 0;
+            }
+            dragable {
+               events: "elm.arrow";
+            }
+         }
+         part { name: "elm.l_button";
+            type: SWALLOW;
+            mouse_events: 1;
+            scale: 1;
+            description { state: "default" 0.0;
+               min: 24 24;
+               fixed: 1 1;
+               rel1 {
+                  relative: 0.0 0.0;
+                  to_y: "elm.bar_bg";
+               }
+               rel2 {
+                  relative: 0.0 1.0;
+                  to_y: "elm.bar_bg";
+               }
+               align: 0.0 0.5;
+            }
+         }
+         part { name: "elm.r_button";
+            type: SWALLOW;
+            mouse_events: 1;
+            scale: 1;
+            description {
+               state: "default" 0.0;
+               min: 24 24;
+               fixed: 1 1;
+               rel1 {
+                  relative: 1.0 0.0;
+                  to_y: "elm.bar_bg";
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  to_y: "elm.bar_bg";
+               }
+               align: 1.0 0.5;
+            }
+         }
+      }
+   }
+
+   group{ name: "elm/colorselector/image/colorbar_0";
+      images {
+         image: "color_picker_color.png" COMP;
+      }
+      parts {
+         part { name: "colorbar_0_image";
+            type: IMAGE;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel2.offset: -1 -1;
+               image.normal: "color_picker_color.png";
+            }
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/image/colorbar_1";
+      images {
+         image: "color_picker_opacity.png" COMP;
+      }
+      parts {
+         part { name: "colorbar_1_image";
+            type: IMAGE;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel2.offset: -1 -1;
+               image.normal: "color_picker_opacity.png";
+            }
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/image/colorbar_2";
+      images {
+         image: "color_picker_brightness.png" COMP;
+      }
+      parts {
+         part { name: "colorbar_2_image";
+            type: IMAGE;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel2.offset: -1 -1;
+               image.normal: "color_picker_brightness.png";
+            }
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/image/colorbar_3";
+      images {
+         image: "color_picker_alpha.png" COMP;
+      }
+      parts {
+         part { name: "colorbar_3_image";
+            type: IMAGE;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel2.offset: -1 -1;
+               image.normal: "color_picker_alpha.png";
+            }
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/bg_image/colorbar_3";
+      images {
+         image: "color_picker_alpha_bg.png" COMP;
+      }
+      parts {
+         part { name: "colorbar_3_image";
+            type: IMAGE;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               rel2.offset: -1 -1;
+               image.normal: "color_picker_alpha_bg.png";
+            }
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/image/updown";
+      images {
+         image: "icon_arrow_down.png" COMP;
+      }
+      parts {
+         part { name: "bg";
+            type: RECT;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               color: 0 0 0 0;
+            }
+         }
+         part { name: "arrow_image";
+            type: IMAGE;
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               image.normal: "icon_arrow_down.png";
+            }
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/button/left";
+      images {
+         image: "bt_base1.png" COMP;
+         image: "bt_shine.png" COMP;
+         image: "sp_bt_l.png" COMP;
+      }
+      parts {
+         part { name: "button_image";
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               image.normal: "bt_base1.png";
+               image.border: 6 6 6 6;
+               image.middle: SOLID;
+            }
+
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "bt_shine.png";
+               image.border: 6 6 6 6;
+               image.middle: SOLID;
+            }
+         }
+         part { name: "btn_over";
+            type: IMAGE;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button_image";
+               rel2 {
+                  relative: 1.0 0.5;
+                  to: "button_image";
+               }
+               image {
+                  normal: "bt_hilight.png";
+                  border: 7 7 7 0;
+               }
+            }
+         }
+         part { name: "btn_over2";
+            type: IMAGE;
+            mouse_events: 1;
+            repeat_events: 1;
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               rel1.to: "button_image";
+               rel2.to: "button_image";
+               image {
+                  normal: "bt_shine.png";
+                  border: 7 7 7 7;
+               }
+            }
+         }
+         part { name: "focus_image";
+            type: IMAGE;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               rel1.to: "button_image";
+               rel2.to: "button_image";
+               image {
+                  normal: "bt_glow.png";
+                  border: 12 12 12 12;
+               }
+               fill.smooth: 0;
+
+            }
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "left_arrow";
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 16 16;
+               max: 16 16;
+               image.normal: "sp_bt_l.png";
+            }
+         }
+      }
+
+      programs {
+         program {
+            name:   "button_down";
+            signal: "elm,state,left,button,down";
+            source: "left_button";
+            action: STATE_SET "clicked" 0.0;
+            target: "button_image";
+            target: "focus_image";
+         }
+         program {
+            name:   "button_up";
+            signal: "elm,state,left,button,up";
+            source: "left_button";
+            action: STATE_SET "default" 0.0;
+            target: "button_image";
+            target: "focus_image";
+         }
+      }
+   }
+
+   group { name: "elm/colorselector/button/right";
+      images {
+         image: "bt_base1.png" COMP;
+         image: "bt_shine.png" COMP;
+         image: "sp_bt_r.png" COMP;
+      }
+      parts {
+         part { name: "button_image";
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               image.normal: "bt_base1.png";
+               image.border: 6 6 6 6;
+               image.middle: SOLID;
+            }
+
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0;
+               image.normal: "bt_shine.png";
+               image.border: 6 6 6 6;
+               image.middle: SOLID;
+            }
+         }
+         part { name: "btn_over";
+            type: IMAGE;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "button_image";
+               rel2 {
+                  relative: 1.0 0.5;
+                  to: "button_image";
+               }
+               image {
+                  normal: "bt_hilight.png";
+                  border: 7 7 7 0;
+               }
+            }
+         }
+         part { name: "btn_over2";
+            type: IMAGE;
+            mouse_events: 1;
+            repeat_events: 1;
+            ignore_flags: ON_HOLD;
+            description { state: "default" 0.0;
+               rel1.to: "button_image";
+               rel2.to: "button_image";
+               image {
+                  normal: "bt_shine.png";
+                  border: 7 7 7 7;
+               }
+            }
+         }
+         part { name: "focus_image";
+            type: IMAGE;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               rel1.to: "button_image";
+               rel2.to: "button_image";
+               image {
+                  normal: "bt_glow.png";
+                  border: 12 12 12 12;
+               }
+               fill.smooth: 0;
+
+            }
+            description { state: "clicked" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               color: 255 255 255 255;
+            }
+         }
+         part { name: "right_arrow";
+            mouse_events: 1;
+            description { state: "default" 0.0;
+               min: 16 16;
+               max: 16 16;
+               image.normal: "sp_bt_r.png";
+            }
+         }
+      }
+
+      programs {
+         program {
+            name:   "button_down";
+            signal: "elm,state,right,button,down";
+            source: "right_button";
+            action: STATE_SET "clicked" 0.0;
+            target: "button_image";
+            target: "focus_image";
+         }
+         program {
+            name:   "button_up";
+            signal: "elm,state,right,button,up";
+            source: "right_button";
+            action: STATE_SET "default" 0.0;
+            target: "button_image";
+            target: "focus_image";
+         }
+      }
+   }
+
+///////////////////////////////////////////////////////////////////////////////
+#define FLIP_PICKER_MAX_LEN (50)
+#define FLIP_PICKER_MAX_LEN_STR "50"
+
+   group { name: "elm/flipselector/base/default";
+      images {
+         image: "flip_base.png" COMP;
+         image: "flip_base_shad.png" COMP;
+         image: "flip_shad.png" COMP;
+         image: "arrow_up.png" COMP;
+         image: "arrow_down.png" COMP;
+         image: "flip_t.png" COMP;
+         image: "flip_b.png" COMP;
+      }
+
+      data {
+         item: "max_len" FLIP_PICKER_MAX_LEN_STR;
+      }
+
+      //FIXME: quick successive clicks on, say, up, lead to nastiness
+      script {
+        public cur, prev, next, lock;
+
+         public animator_bottom_down(val, Float:pos) {
+            new tmp[FLIP_PICKER_MAX_LEN];
+
+            set_tween_state(PART:"bottom", pos, "shrink", 0.0, "default", 0.0);
+            set_tween_state(PART:"bottom_sheet", pos, "shrink", 0.0, "default",
+                            0.0);
+            set_tween_state(PART:"shadow", pos, "half", 0.0, "full",
+                            0.0);
+
+            if (pos >= 1.0) {
+               set_state(PART:"shadow", "default", 0.0);
+               set_int(lock, 0);
+
+               fetch_str(next, 0, tmp, FLIP_PICKER_MAX_LEN);
+               if (strncmp(tmp, "", FLIP_PICKER_MAX_LEN) != 0) {
+                  replace_str(next, 0, "");
+                  message(MSG_STRING, 1, tmp);
+               }
+            }
+         }
+
+         public animator_top_down(val, Float:pos) {
+            set_tween_state(PART:"top", pos, "default", 0.0, "shrink", 0.0);
+            set_tween_state(PART:"top_sheet", pos, "default", 0.0, "shrink",
+                            0.0);
+            set_tween_state(PART:"shadow", pos, "default", 0.0, "half",
+                            0.0);
+
+            if (pos >= 1.0)
+               anim(0.2, "animator_bottom_down", val);
+         }
+
+         public animator_bottom_up(val, Float:pos) {
+            set_tween_state(PART:"bottom", pos, "default", 0.0, "shrink", 0.0);
+            set_tween_state(PART:"bottom_sheet", pos, "default", 0.0, "shrink",
+                            0.0);
+            set_tween_state(PART:"shadow", pos, "full", 0.0, "half",
+                            0.0);
+
+            if (pos >= 1.0)
+               anim(0.2, "animator_top_up", val);
+         }
+
+         public animator_top_up(val, Float:pos) {
+            new tmp[FLIP_PICKER_MAX_LEN];
+
+            set_tween_state(PART:"top", pos, "shrink", 0.0, "default", 0.0);
+            set_tween_state(PART:"top_sheet", pos, "shrink", 0.0, "default",
+                            0.0);
+            set_tween_state(PART:"shadow", pos, "half", 0.0, "default",
+                            0.0);
+
+            if (pos >= 1.0) {
+               set_state(PART:"shadow", "default", 0.0);
+               set_int(lock, 0);
+
+               fetch_str(next, 0, tmp, FLIP_PICKER_MAX_LEN);
+               if (strncmp(tmp, "", FLIP_PICKER_MAX_LEN) != 0) {
+                  replace_str(next, 0, "");
+                  message(MSG_STRING, 2, tmp);
+               }
+            }
+         }
+
+         public message(Msg_Type:type, id, ...) {
+            /* flip down */
+            if ((type == MSG_STRING) && (id == 1)) {
+               new value[FLIP_PICKER_MAX_LEN], tmp[FLIP_PICKER_MAX_LEN];
+
+               snprintf(value, FLIP_PICKER_MAX_LEN, "%s", getarg(2));
+
+               if (get_int(lock) == 1) {
+                  replace_str(next, 0, value);
+                  return;
+               }
+
+               fetch_str(cur, 0, tmp, FLIP_PICKER_MAX_LEN);
+
+               set_text(PART:"bottom_b", tmp);
+
+               set_state(PART:"top", "shrink", 0.0);
+               set_text(PART:"top", tmp);
+               set_state(PART:"top", "default", 0.0);
+               set_text(PART:"top", tmp);
+
+               replace_str(prev, 0, tmp);
+
+               set_state(PART:"bottom", "default", 0.0);
+               set_text(PART:"bottom", value);
+               set_state(PART:"bottom", "shrink", 0.0);
+               set_text(PART:"bottom", value);
+
+               set_text(PART:"top_b", value);
+
+               replace_str(cur, 0, value);
+
+               set_state(PART:"bottom_sheet", "shrink", 0.0);
+               set_state(PART:"top_sheet", "default", 0.0);
+
+               set_int(lock, 1);
+               set_state(PART:"shadow", "default", 0.0);
+               anim(0.2, "animator_top_down", 1);
+            }
+
+            /* flip up */
+            if ((type == MSG_STRING) && (id == 2)) {
+               new value[FLIP_PICKER_MAX_LEN], tmp[FLIP_PICKER_MAX_LEN];
+
+               snprintf(value, FLIP_PICKER_MAX_LEN, "%s", getarg(2));
+
+               if (get_int(lock) == 1) {
+                  replace_str(next, 0, value);
+                  return;
+               }
+
+               fetch_str(cur, 0, tmp, FLIP_PICKER_MAX_LEN);
+
+               set_text(PART:"top_b", tmp);
+
+               set_state(PART:"bottom", "shrink", 0.0);
+               set_text(PART:"bottom", tmp);
+               set_state(PART:"bottom", "default", 0.0);
+               set_text(PART:"bottom", tmp);
+
+               replace_str(prev, 0, tmp);
+
+               set_state(PART:"top", "default", 0.0);
+               set_text(PART:"top", value);
+               set_state(PART:"top", "shrink", 0.0);
+               set_text(PART:"top", value);
+
+               set_text(PART:"bottom_b", value);
+
+               replace_str(cur, 0, value);
+
+               set_state(PART:"bottom_sheet", "default", 0.0);
+               set_state(PART:"top_sheet", "shrink", 0.0);
+
+               set_int(lock, 1);
+               set_state(PART:"shadow", "full", 0.0);
+               anim(0.2, "animator_bottom_up", 1);
+            }
+         }
+      }
+
+      parts {
+        part { name: "shad";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.offset: -4 -4;
+              rel1.to: "base";
+              rel2.offset: 3 3;
+              rel2.to: "base";
+              image {
+                  normal: "flip_base_shad.png";
+                 border: 8 8 8 8;
+              }
+           }
+        }
+
+        part { name: "base";
+           scale: 1;
+           description { state: "default" 0.0;
+              rel1.offset: 4 4;
+              rel2.offset: -5 -5;
+              min: 24 48;
+              image.normal: "flip_base.png";
+           }
+        }
+
+        part { name: "b";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "base";
+              rel1.relative: 0.0 0.5;
+              rel2.to: "base";
+              color: 0 0 0 0;
+           }
+           description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+           }
+        }
+
+        part { name: "t";
+           type: RECT;
+           mouse_events: 1;
+           description { state: "default" 0.0;
+              rel1.to: "base";
+              rel2.to: "base";
+              rel2.relative: 1.0 0.5;
+              color: 0 0 0 0;
+           }
+           description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+           }
+        }
+
+        part { name: "bottom_sheet_static";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "flip_b.png";
+           }
+         }
+
+        part { name: "bottom_b";
+           mouse_events: 0;
+            clip_to: "bottom_clipper";
+            type: TEXT;
+            scale: 1;
+           description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               color: 0 0 0 255;
+               color2: 0 0 0 255;
+               text {
+                  font: "Sans:style=Bold,Edje-Vera-Bold";
+                  size: 30;
+                  min: 1 1;
+                  align: 0.5 0.5;
+               }
+            }
+         }
+
+        part { name: "shadow";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              rel2.relative: 1.0 0.0;
+              image.normal: "flip_shad.png";
+           }
+           description { state: "half" 0.0;
+              inherit: "default" 0.0;
+              rel2.relative: 1.0 0.5;
+           }
+           description { state: "full" 0.0;
+              inherit: "default" 0.0;
+              rel2.relative: 1.0 1.0;
+           }
+        }
+
+        part { name: "bottom_sheet";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "flip_b.png";
+           }
+           description { state: "shrink" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel2.relative: 1.0 0.0;
+           }
+         }
+
+        part { name: "bottom";
+           mouse_events: 0;
+            clip_to: "bottom_clipper";
+            type: TEXT;
+            scale: 1;
+           description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               color: 0 0 0 255;
+               color2: 0 0 0 255;
+               text {
+                  font: "Sans:style=Bold,Edje-Vera-Bold";
+                  size: 30;
+                  min: 1 1;
+                  align: 0.5 0.5;
+               }
+            }
+           description { state: "shrink" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel2.relative: 1.0 0.5; /* FIXME: same visual effect? --> MAP! */
+           }
+         }
+
+        part { name: "top_sheet_static";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "flip_t.png";
+           }
+         }
+
+        part { name: "top_b";
+           mouse_events: 0;
+            clip_to: "top_clipper";
+            type: TEXT;
+            scale: 1;
+           description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               color: 0 0 0 255;
+               color2: 0 0 0 255;
+               text {
+                  font: "Sans:style=Bold,Edje-Vera-Bold";
+                  size: 30;
+                  min: 1 1;
+                  align: 0.5 0.5;
+                  source: "top";
+               }
+            }
+         }
+
+        part { name: "top_sheet";
+           mouse_events: 0;
+           description { state: "default" 0.0;
+              visible: 1;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "flip_t.png";
+           }
+           description { state: "shrink" 0.0;
+              inherit: "default" 0.0;
+              color: 128 128 128 255;
+              visible: 0;
+              rel1.relative: 0.0 1.0;
+           }
+         }
+
+        part { name: "top";
+           mouse_events: 0;
+            clip_to: "top_clipper";
+            type: TEXT;
+            scale: 1;
+           description { state: "default" 0.0;
+               rel1.to: "base";
+               rel2.to: "base";
+               color: 0 0 0 255;
+               color2: 0 0 0 255;
+               text {
+                  font: "Sans:style=Bold,Edje-Vera-Bold";
+                  size: 30;
+                  min: 1 1;
+                  align: 0.5 0.5;
+               }
+            }
+           description { state: "shrink" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+              rel1.relative: 0.0 0.5;
+           }
+         }
+
+        part { name: "arrow_top";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              min: 15 15;
+              max: 15 15;
+              align: 0.5 0.0;
+              rel1.to: "t";
+              rel2.to: "t";
+              image.normal: "arrow_up.png";
+           }
+           description { state: "hidden" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+           }
+        }
+        part { name: "arrow_bottom";
+           mouse_events: 0;
+           scale: 1;
+           description { state: "default" 0.0;
+              min: 15 15;
+              max: 15 15;
+              align: 0.5 1.0;
+              rel1.to: "b";
+              rel2.to: "b";
+              image.normal: "arrow_down.png";
+           }
+           description { state: "hidden" 0.0;
+              inherit: "default" 0.0;
+              visible: 0;
+           }
+        }
+
+         part {
+            type: RECT;
+            mouse_events: 0;
+            name: "top_clipper";
+            description {
+               state: "default" 0.0;
+               rel1.to: "t";
+               rel2.to: "t";
+               visible: 1;
+            }
+         }
+
+         part {
+            type: RECT;
+            mouse_events: 0;
+            name: "bottom_clipper";
+            description {
+               state: "default" 0.0;
+               rel1.to: "b";
+               rel2.to: "b";
+               visible: 1;
+            }
+         }
+      }
+
+      programs {
+        program { name: "load";
+           signal: "load";
+           source: "";
+           script {
+              append_str(cur, "");
+              append_str(prev, "");
+              append_str(next, "");
+              set_int(lock, 0);
+           }
+        }
+
+         program { name: "hide_arrows";
+            signal: "elm,state,button,hidden";
+            source: "elm";
+            action: STATE_SET "hidden" 0.0;
+            target: "arrow_top";
+            target: "arrow_bottom";
+            target: "t";
+            target: "b";
+         }
+
+         program { name: "show_arrows";
+            signal: "elm,state,button,visible";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "arrow_top";
+            target: "arrow_bottom";
+            target: "t";
+            target: "b";
+         }
+
+        program { name: "up";
+           signal: "mouse,down,1";
+           source: "t";
+           action: SIGNAL_EMIT "elm,action,up,start" "";
+        }
+        program { name: "up,stop";
+           signal: "mouse,up,1";
+           source: "t";
+           action: SIGNAL_EMIT "elm,action,up,stop" "";
+        }
+        program { name: "down";
+           signal: "mouse,down,1";
+           source: "b";
+           action: SIGNAL_EMIT "elm,action,down,start" "";
+        }
+        program { name: "down,stop";
+           signal: "mouse,up,1";
+           source: "b";
+           action: SIGNAL_EMIT "elm,action,down,stop" "";
+        }
+      }
+   }
+
+////////////////////////////////////////////////////////////////////////////////
+// diskselector
+////////////////////////////////////////////////////////////////////////////////
+   group { name: "elm/diskselector/base/default";
+      images {
+         image: "bar_shine.png" COMP;
+      }
+
+      parts {
+         part { name: "bg";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               color: 0 0 0 255;
+            }
+         }
+         part { name: "shine_left";
+            mouse_events:  0;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel1.relative: -0.1 0;
+               rel2.to: "bg";
+               rel2.relative: 0.1 1;
+               image.normal: "bar_shine.png";
+               color: 255 255 255 120;
+            }
+         }
+         part { name: "shine_center";
+            mouse_events:  0;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel1.relative: 0.2 0;
+               rel2.to: "bg";
+               rel2.relative: 0.8 1;
+               image.normal: "bar_shine.png";
+               color: 255 255 255 180;
+            }
+         }
+         part { name: "shine_right";
+            mouse_events:  0;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel1.relative: 0.9 0;
+               rel2.to: "bg";
+               rel2.relative: 1.1 1;
+               image.normal: "bar_shine.png";
+               color: 255 255 255 120;
+            }
+         }
+         part { name: "clipper";
+            type: RECT;
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+               rel1.offset: 2 2;
+               rel2.offset: -3 -3;
+            }
+         }
+         part { name: "elm.swallow.content";
+            clip_to: "clipper";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               rel1.to: "bg";
+               rel2.to: "bg";
+            }
+         }
+      }
+   }
+
+   group { name: "elm/diskselector/item/default";
+
+      data {
+         item: "len_threshold" "14";
+      }
+
+      parts {
+         part { name: "elm.swallow.icon";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               fixed: 1 0;
+               align: 0.0 0.5;
+               rel1 {
+                  relative: 0 0;
+                  offset: 4 4;
+               }
+               rel2 {
+                  relative: 0 1;
+                  offset: 4 -5;
+               }
+            }
+            description { state: "show" 0.0;
+               inherit: "default" 0.0;
+            }
+            description { state: "default_small" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0 0.2;
+               rel2.relative: 0 0.8;
+            }
+            description { state: "left_side" 0.0;
+               inherit: "default" 0.0;
+               rel1.relative: 0 0.2;
+               rel2.relative: 0 0.8;
+               color: 255 255 255 160;
+            }
+            description { state: "right_side" 0.0;
+               inherit: "left_side" 0.0;
+               rel1.relative: 0.4 0.2;
+               rel2.relative: 0.4 0.8;
+               color: 255 255 255 160;
+            }
+         }
+         part { name: "elm.text";
+            type: TEXT;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1.relative: 1 0.0;
+               rel1.to_x: "elm.swallow.icon";
+               rel2.relative: 1.0 1.0;
+               color: 255 255 255 255;
+               visible: 0;
+               text {
+                  font: "Sans,Edje-Vera";
+                  size: 13;
+                  align: 0.5 0.5;
+                  min: 0 1;
+               }
+            }
+            description { state: "show" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "default_small" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+               text.size: 10;
+            }
+            description { state: "left_side" 0.0;
+               inherit: "default" 0.0;
+               color: 172 172 172 255;
+               text.size: 10;
+               visible: 1;
+               text.align: 0.2 0.5;
+            }
+            description { state: "right_side" 0.0;
+               inherit: "default" 0.0;
+               color: 172 172 172 255;
+               visible: 1;
+               text.size: 10;
+               text.align: 0.8 0.5;
+            }
+         }
+      }
+
+      programs {
+         program { name: "center_text";
+            signal: "elm,state,center";
+            source: "elm";
+            action: STATE_SET "show" 0.0;
+            target: "elm.text";
+            target: "elm.swallow.icon";
+         }
+         program { name: "center_small_text";
+            signal: "elm,state,center_small";
+            source: "elm";
+            action: STATE_SET "default_small" 0.0;
+            target: "elm.text";
+            target: "elm.swallow.icon";
+         }
+         program { name: "l_side_text";
+            signal: "elm,state,left_side";
+            source: "elm";
+            action: STATE_SET "left_side" 0.0;
+            target: "elm.text";
+            target: "elm.swallow.icon";
+         }
+         program { name: "r_side_text";
+            signal: "elm,state,right_side";
+            source: "elm";
+            action: STATE_SET "right_side" 0.0;
+            target: "elm.text";
+            target: "elm.swallow.icon";
+         }
+      }
+   }
+
+   group { name: "elm/entry/path/separator/default";
+      images.image: "arrow_right.png" COMP;
+      parts {
+         part { name: "icon";
+            mouse_events: 0;
+            description { state: "default" 0.0;
+               image.normal: "arrow_right.png";
+               max: 64 64;
+               aspect: 1.0 1.0;
+            }
+         }
+      }
+   }
+
+   group { name: "elm/fileselector/base/default";
+      data {
+         item: "path_separator" "<item relsize=16x16 vsize=full href=path/separator></item>";
+      }
+      parts {
+         part { name: "elm.swallow.up";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 10 10;
+               fixed: 1 1;
+               rel2 {
+                  relative: 0.0 0.0;
+                  offset: 0 0;
+               }
+            }
+         }
+         part { name: "elm.swallow.home";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 10 10;
+               fixed: 1 1;
+               rel1 {
+                  to: "elm.swallow.up";
+                  relative: 1.0 0.0;
+                  offset: 5 0;
+               }
+               rel2 {
+                  to: "elm.swallow.up";
+                  relative: 1.0 1.0;
+                  offset: 20 -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.files";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 1.0 0.0;
+               min: 10 10;
+               fixed: 1 1;
+               rel1 {
+                  to_y: "elm.swallow.home";
+                  relative: 0.0 1.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to_y: "elm.swallow.path";
+                  relative: 1.0 0.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.path";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 0.5 1.0;
+               fixed: 1 1;
+               rel1 {
+                  to_y: "elm.swallow.filename";
+                  relative: 0.0 0.0;
+                  offset: 0 -1;
+               }
+               rel2 {
+                  to_y: "elm.swallow.filename";
+                  relative: 1.0 0.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.filename";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 0.5 1.0;
+               fixed: 1 1;
+               rel1 {
+                  to_y: "elm.swallow.ok";
+                  relative: 0.0 0.0;
+                  offset: 0 -1;
+               }
+               rel2 {
+                  to_y: "elm.swallow.ok";
+                  relative: 1.0 0.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.cancel";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 1.0 1.0;
+               fixed: 1 1;
+               rel1 {
+                  to: "elm.swallow.ok";
+                  relative: 0.0 0.0;
+                  offset: -3 0;
+               }
+               rel2 {
+                  to: "elm.swallow.ok";
+                  relative: 0.0 1.0;
+                  offset: -3 -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.ok";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 1.0 1.0;
+               fixed: 1 1;
+               rel1 {
+                  relative: 1.0 1.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+      }
+   }
+
+   group { name: "elm/fileselector_entry/base/default";
+      parts {
+         part { name: "elm.swallow.entry";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               min: 50 10;
+               rel2 { to_x: "elm.swallow.button";
+                  relative: 0.0 1.0;
+                  offset: -1 -1;
+               }
+            }
+         }
+         part { name: "elm.swallow.button";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 1.0 0.0;
+               min: 10 10;
+               fixed: 1 1;
+               rel1 {
+                  relative: 1.0 0.0;
+                  offset: -21 0;
+               }
+            }
+         }
+      }
+   }
+
+////////////////////////////////////////////////////////////////////////
+// Standard layouts to be used                                        //
+////////////////////////////////////////////////////////////////////////
+   /* application with toolbar and main content area */
+   group { name: "elm/layout/application/toolbar-content";
+      parts {
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               rel1 { to_y: "elm.external.toolbar";
+                  relative: 0.0 1.0;
+                  offset: -1 1;
+               }
+            }
+         }
+
+         part { name: "elm.external.toolbar";
+            type: EXTERNAL;
+            source: "elm/toolbar";
+            description { state: "default" 0.0;
+               align: 0.5 0.0;
+               fixed: 0 1;
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -1 47;
+               }
+            }
+         }
+      }
+   }
+
+   /* application with toolbar and main content area with a back button and title area */
+   group { name: "elm/layout/application/toolbar-content-back";
+      parts {
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               rel1 { to_y: "title_clipper";
+                  relative: 0.0 1.0;
+                  offset: -1 1;
+               }
+            }
+         }
+
+         part { name: "elm.external.toolbar";
+            type: EXTERNAL;
+            source: "elm/toolbar";
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 0.0;
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -1 47;
+               }
+            }
+         }
+         part { name: "title_clipper";
+            type: RECT;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 {
+                  to_y: "back";
+               }
+               rel2 {
+                  to_y: "back";
+               }
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               rel2 {
+                  relative: 1.0 0.0;
+               }
+            }
+         }
+         part { name: "back_clipper";
+            type: RECT;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+            }
+         }
+         part { name: "back";
+            type: EXTERNAL;
+            source: "elm/button";
+            clip_to: "back_clipper";
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               fixed: 1 1;
+               rel1 { to_y: "elm.external.toolbar";
+                  relative: 0.0 1.0;
+                  offset: 0 1;
+               }
+               rel2 { to_y: "elm.external.toolbar";
+                  relative: 0.0 1.0;
+                  offset: 50 32;
+               }
+               params.string: "label" "Back";
+            }
+         }
+         programs {
+            program {
+               signal: "clicked";
+               source: "back";
+               action: SIGNAL_EMIT "elm,action,back" "";
+            }
+            program {
+               signal: "elm,back,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "elm,back,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "elm,title,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.1;
+               target: "title_clipper";
+            }
+            program {
+               signal: "elm,title,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "title_clipper";
+            }
+         }
+
+         part { name: "elm.swallow.end";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 1.0 0.0;
+               fixed: 1 1;
+               rel1 { to_y: "elm.external.toolbar";
+                  relative: 1.0 1.0;
+                  offset: -2 1;
+               }
+               rel2 { to_y: "elm.external.toolbar";
+                  relative: 1.0 1.0;
+                  offset: -1 32;
+               }
+            }
+         }
+
+         part { name: "elm.text.title";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1 { to_y: "elm.external.toolbar";
+                  to_x: "back";
+                  relative: 1.0 1.0;
+                  offset: 2 1;
+               }
+               rel2 { to_y: "back";
+                  to_x: "elm.swallow.end";
+                  relative: 0.0 1.0;
+                  offset: -3 -1;
+               }
+               text {
+                  font: "Sans:style=Bold";
+                  size: 12;
+               }
+            }
+         }
+      }
+   }
+
+   /* application with toolbar and main content area with a back and next buttons and title area */
+   group { name: "elm/layout/application/toolbar-content-back-next";
+      parts {
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               rel1 { to_y: "title_clipper";
+                  relative: 0.0 1.0;
+                  offset: -1 1;
+               }
+            }
+         }
+
+         part { name: "elm.external.toolbar";
+            type: EXTERNAL;
+            source: "elm/toolbar";
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               align: 0.5 0.0;
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -1 47;
+               }
+            }
+         }
+         part { name: "title_clipper";
+            type: RECT;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 {
+                  to_y: "back";
+               }
+               rel2 {
+                  to_y: "back";
+               }
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               rel2 {
+                  relative: 1.0 0.0;
+               }
+            }
+         }
+         part { name: "back";
+            type: EXTERNAL;
+            source: "elm/button";
+            clip_to: "back_clipper";
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               fixed: 1 1;
+               rel1 { to_y: "elm.external.toolbar";
+                  relative: 0.0 1.0;
+                  offset: 0 1;
+               }
+               rel2 { to_y: "elm.external.toolbar";
+                  relative: 0.0 1.0;
+                  offset: 50 32;
+               }
+               params.string: "label" "Back";
+            }
+         }
+         part { name: "back_clipper";
+            type: RECT;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+            }
+         }
+         part { name: "next";
+            type: EXTERNAL;
+            source: "elm/button";
+            clip_to: "next_clipper";
+            description { state: "default" 0.0;
+               align: 1.0 0.0;
+               fixed: 1 1;
+               rel1 { to_y: "elm.external.toolbar";
+                  relative: 1.0 1.0;
+                  offset: -2 1;
+               }
+               rel2 { to_y: "elm.external.toolbar";
+                  relative: 1.0 1.0;
+                  offset: -1 32;
+               }
+               params.string: "label" "Next";
+           }
+         }
+         part { name: "next_clipper";
+            type: RECT;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+            }
+         }
+         programs {
+            program {
+               signal: "clicked";
+               source: "back";
+               action: SIGNAL_EMIT "elm,action,back" "";
+            }
+            program {
+               signal: "elm,title,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.1;
+               target: "title_clipper";
+            }
+            program {
+               signal: "elm,title,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "title_clipper";
+            }
+            program {
+               signal: "elm,back,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "elm,back,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "clicked";
+               source: "next";
+               action: SIGNAL_EMIT "elm,action,next" "";
+            }
+            program {
+               signal: "elm,next,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "next_clipper";
+            }
+            program {
+               signal: "elm,next,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "next_clipper";
+            }
+         }
+         part { name: "elm.text.title";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            scale: 1;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               rel1 { to_y: "elm.external.toolbar";
+                  to_x: "back";
+                  relative: 1.0 1.0;
+                  offset: 2 1;
+               }
+               rel2 { to_y: "back";
+                  to_x: "next";
+                  relative: 0.0 1.0;
+                  offset: -3 -1;
+               }
+               text {
+                  font: "Sans:style=Bold";
+                  size: 12;
+               }
+            }
+         }
+      }
+   }
+   /* application with a main content area with a back button and title area */
+   group { name: "elm/layout/application/content-back";
+      parts {
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               rel1 { to_y: "title_clipper";
+                  relative: 0.0 1.0;
+                  offset: -1 1;
+               }
+            }
+         }
+         part { name: "title_clipper";
+            type: RECT;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 {
+                  to_y: "back";
+               }
+               rel2 {
+                  to_y: "back";
+               }
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               rel2 {
+                  relative: 1.0 0.0;
+               }
+            }
+         }
+         part { name: "back_clipper";
+            type: RECT;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+            }
+         }
+         part { name: "back";
+            type: EXTERNAL;
+            source: "elm/button";
+            clip_to: "back_clipper";
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               fixed: 1 1;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 0 1;
+               }
+               rel2 {
+                  relative: 0.0 0.0;
+                  offset: 50 32;
+               }
+               params.string: "label" "Back";
+            }
+         }
+         programs {
+            program {
+               signal: "clicked";
+               source: "back";
+               action: SIGNAL_EMIT "elm,action,back" "";
+            }
+            program {
+               signal: "elm,back,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "elm,back,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "elm,title,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.1;
+               target: "title_clipper";
+            }
+            program {
+               signal: "elm,title,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "title_clipper";
+            }
+         }
+
+         part { name: "elm.swallow.end";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               align: 1.0 0.0;
+               fixed: 1 1;
+               rel1 {
+                  relative: 1.0 0.0;
+                  offset: -2 1;
+               }
+               rel2 {
+                  relative: 1.0 1.0;
+                  offset: -1 32;
+               }
+            }
+         }
+
+         part { name: "elm.text.title";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  to_x: "back";
+                  relative: 1.0 0.0;
+                  offset: 2 1;
+               }
+               rel2 { to_y: "back";
+                  to_x: "elm.swallow.end";
+                  relative: 0.0 1.0;
+                  offset: -3 -1;
+               }
+               text {
+                  font: "Sans:style=Bold";
+                  size: 12;
+               }
+            }
+         }
+      }
+   }
+
+   /* application with a main content area with a back and next buttons and title area */
+   group { name: "elm/layout/application/content-back-next";
+      parts {
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               rel1 { to_y: "title_clipper";
+                  relative: 0.0 1.0;
+                  offset: -1 1;
+               }
+            }
+         }
+
+         part { name: "title_clipper";
+            type: RECT;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 {
+                  to_y: "back";
+               }
+               rel2 {
+                  to_y: "back";
+               }
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               visible: 0;
+               rel2 {
+                  relative: 1.0 0.0;
+               }
+            }
+         }
+         part { name: "back";
+            type: EXTERNAL;
+            source: "elm/button";
+            clip_to: "back_clipper";
+            description { state: "default" 0.0;
+               align: 0.0 0.0;
+               fixed: 1 1;
+               rel1 {
+                  relative: 0.0 0.0;
+                  offset: 0 1;
+               }
+               rel2 {
+                  relative: 0.0 0.0;
+                  offset: 50 32;
+               }
+               params.string: "label" "Back";
+            }
+         }
+         part { name: "back_clipper";
+            type: RECT;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+            }
+         }
+         part { name: "next";
+            type: EXTERNAL;
+            source: "elm/button";
+            clip_to: "next_clipper";
+            description { state: "default" 0.0;
+               align: 1.0 0.0;
+               fixed: 1 1;
+               rel1 {
+                  relative: 1.0 0.0;
+                  offset: -2 1;
+               }
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -1 32;
+               }
+               params.string: "label" "Next";
+           }
+         }
+         part { name: "next_clipper";
+            type: RECT;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               visible: 0;
+            }
+         }
+         programs {
+            program {
+               signal: "clicked";
+               source: "back";
+               action: SIGNAL_EMIT "elm,action,back" "";
+            }
+            program {
+               signal: "elm,title,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               transition: LINEAR 0.1;
+               target: "title_clipper";
+            }
+            program {
+               signal: "elm,title,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "title_clipper";
+            }
+            program {
+               signal: "elm,back,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "elm,back,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "back_clipper";
+            }
+            program {
+               signal: "clicked";
+               source: "next";
+               action: SIGNAL_EMIT "elm,action,next" "";
+            }
+            program {
+               signal: "elm,next,hide";
+               source: "elm";
+               action: STATE_SET "hidden" 0.0;
+               target: "next_clipper";
+            }
+            program {
+               signal: "elm,next,show";
+               source: "elm";
+               action: STATE_SET "default" 0.0;
+               target: "next_clipper";
+            }
+         }
+         part { name: "elm.text.title";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            scale: 1;
+            clip_to: "title_clipper";
+            description { state: "default" 0.0;
+               rel1 {
+                  to_x: "back";
+                  relative: 1.0 0.0;
+                  offset: 2 1;
+               }
+               rel2 { to_y: "back";
+                  to_x: "next";
+                  relative: 0.0 1.0;
+                  offset: -3 -1;
+               }
+               text {
+                  font: "Sans:style=Bold";
+                  size: 12;
+               }
+            }
+         }
+      }
+   }
+
+   /* application with toolbar and main content area as a vertical box */
+   group { name: "elm/layout/application/toolbar-vbox";
+      parts {
+         part { name: "elm.box.content";
+            type: BOX;
+            description { state: "default" 0.0;
+               rel1 { to_y: "elm.external.toolbar";
+                  relative: 0.0 1.0;
+                  offset: -1 1;
+               }
+               box.layout: "vertical";
+            }
+         }
+
+         part { name: "elm.external.toolbar";
+            type: EXTERNAL;
+            source: "elm/toolbar";
+            description { state: "default" 0.0;
+               align: 0.5 0.0;
+               fixed: 0 1;
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -1 47;
+               }
+            }
+         }
+      }
+   }
+
+   /* application with toolbar and main content area as a table */
+   group { name: "elm/layout/application/toolbar-table";
+      parts {
+         part { name: "elm.table.content";
+            type: TABLE;
+            description { state: "default" 0.0;
+               rel1 { to_y: "elm.external.toolbar";
+                  relative: 0.0 1.0;
+                  offset: -1 1;
+               }
+            }
+         }
+
+         part { name: "elm.external.toolbar";
+            type: EXTERNAL;
+            source: "elm/toolbar";
+            description { state: "default" 0.0;
+               align: 0.5 0.0;
+               fixed: 0 1;
+               rel2 {
+                  relative: 1.0 0.0;
+                  offset: -1 47;
+               }
+            }
+         }
+      }
+   }
+
+   /* a simple title layout, with a label and two icons */
+   group { name: "elm/layout/application/titlebar";
+      images {
+         image: "toolbar_sel.png" COMP;
+      }
+      parts {
+         part { name: "base";
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               min: 0 33;
+               max: 99999 33;
+               align: 0.5 0.0;
+               rel1.offset: -1 0;
+               rel2.offset: 1 0;
+               image {
+                  normal: "toolbar_sel.png";
+                  border: 3 3 0 0;
+               }
+            }
+         }
+         part { name: "elm.swallow.content";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 1.0;
+               }
+            }
+         }
+         part { name: "elm.swallow.icon";
+            type: SWALLOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               visible: 0;
+               fixed: 1 1;
+               align: 0.0 0.0;
+               rel1 {
+                  to: "base";
+                  relative: 0.0 0.0;
+                  offset: 4 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 0.0 1.0;
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+         }
+         part { name: "elm.swallow.end";
+            type: SWALLOW;
+            scale: 1;
+            description { state: "default" 0.0;
+               visible: 0;
+               fixed: 1 1;
+               align: 1.0 0.0;
+               rel1 {
+                  to: "base";
+                  relative: 1.0 0.0;
+                  offset: 0 0;
+               }
+               rel2 {
+                  to: "base";
+                  relative: 1.0 1.0;
+                  offset: -5 -1;
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               visible: 1;
+            }
+         }
+         part { name: "elm.text";
+            type: TEXT;
+            effect: SOFT_SHADOW;
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1 {
+                  to_x: "elm.swallow.icon";
+                  to_y: "base";
+                  relative: 1.0 0.0;
+               }
+               rel2 {
+                  to_x: "elm.swallow.end";
+                  to_y: "base";
+                  relative: 0.0 1.0;
+               }
+               text {
+                  font: "Sans";
+                  size: 12;
+                  min: 0 0;
+                  align: 0.5 0.5;
+                  text_class: "title_bar";
+               }
+            }
+         }
+      }
+      programs {
+         program { name: "show_icon";
+            signal: "elm,state,icon,visible";
+            source: "elm";
+            action: STATE_SET "visible" 0.0;
+            target: "elm.swallow.icon";
+         }
+         program { name: "hide_icon";
+            signal: "elm,state,icon,hidden";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.swallow.icon";
+         }
+         program { name: "show_end";
+            signal: "elm,state,end,visible";
+            source: "elm";
+            action: STATE_SET "visible" 0.0;
+            target: "elm.swallow.end";
+         }
+         program { name: "hide_end";
+            signal: "elm,state,end,hidden";
+            source: "elm";
+            action: STATE_SET "default" 0.0;
+            target: "elm.swallow.end";
+         }
+      }
+   }
+}
+
+
+
+
diff --git a/data/themes/dia_botshad.png b/data/themes/dia_botshad.png
new file mode 100644 (file)
index 0000000..89a598e
Binary files /dev/null and b/data/themes/dia_botshad.png differ
diff --git a/data/themes/dia_grad.png b/data/themes/dia_grad.png
new file mode 100644 (file)
index 0000000..bfd7d0e
Binary files /dev/null and b/data/themes/dia_grad.png differ
diff --git a/data/themes/dia_topshad.png b/data/themes/dia_topshad.png
new file mode 100644 (file)
index 0000000..1a77213
Binary files /dev/null and b/data/themes/dia_topshad.png differ
diff --git a/data/themes/down.png b/data/themes/down.png
new file mode 100644 (file)
index 0000000..528c543
Binary files /dev/null and b/data/themes/down.png differ
diff --git a/data/themes/emo-angry-shout.png b/data/themes/emo-angry-shout.png
new file mode 100644 (file)
index 0000000..25477c5
Binary files /dev/null and b/data/themes/emo-angry-shout.png differ
diff --git a/data/themes/emo-angry.png b/data/themes/emo-angry.png
new file mode 100644 (file)
index 0000000..e151077
Binary files /dev/null and b/data/themes/emo-angry.png differ
diff --git a/data/themes/emo-crazy-laugh.png b/data/themes/emo-crazy-laugh.png
new file mode 100644 (file)
index 0000000..4e87937
Binary files /dev/null and b/data/themes/emo-crazy-laugh.png differ
diff --git a/data/themes/emo-evil-laugh.png b/data/themes/emo-evil-laugh.png
new file mode 100644 (file)
index 0000000..1a0ec3a
Binary files /dev/null and b/data/themes/emo-evil-laugh.png differ
diff --git a/data/themes/emo-evil.png b/data/themes/emo-evil.png
new file mode 100644 (file)
index 0000000..32233fd
Binary files /dev/null and b/data/themes/emo-evil.png differ
diff --git a/data/themes/emo-goggle-smile.png b/data/themes/emo-goggle-smile.png
new file mode 100644 (file)
index 0000000..a0e4859
Binary files /dev/null and b/data/themes/emo-goggle-smile.png differ
diff --git a/data/themes/emo-grumpy-smile.png b/data/themes/emo-grumpy-smile.png
new file mode 100644 (file)
index 0000000..12e301f
Binary files /dev/null and b/data/themes/emo-grumpy-smile.png differ
diff --git a/data/themes/emo-grumpy.png b/data/themes/emo-grumpy.png
new file mode 100644 (file)
index 0000000..7de77fa
Binary files /dev/null and b/data/themes/emo-grumpy.png differ
diff --git a/data/themes/emo-guilty-smile.png b/data/themes/emo-guilty-smile.png
new file mode 100644 (file)
index 0000000..57de06e
Binary files /dev/null and b/data/themes/emo-guilty-smile.png differ
diff --git a/data/themes/emo-guilty.png b/data/themes/emo-guilty.png
new file mode 100644 (file)
index 0000000..071deb0
Binary files /dev/null and b/data/themes/emo-guilty.png differ
diff --git a/data/themes/emo-haha.png b/data/themes/emo-haha.png
new file mode 100644 (file)
index 0000000..760535d
Binary files /dev/null and b/data/themes/emo-haha.png differ
diff --git a/data/themes/emo-half-smile.png b/data/themes/emo-half-smile.png
new file mode 100644 (file)
index 0000000..529f60a
Binary files /dev/null and b/data/themes/emo-half-smile.png differ
diff --git a/data/themes/emo-happy-panting.png b/data/themes/emo-happy-panting.png
new file mode 100644 (file)
index 0000000..c6461bc
Binary files /dev/null and b/data/themes/emo-happy-panting.png differ
diff --git a/data/themes/emo-happy.png b/data/themes/emo-happy.png
new file mode 100644 (file)
index 0000000..a8a3c0b
Binary files /dev/null and b/data/themes/emo-happy.png differ
diff --git a/data/themes/emo-indifferent.png b/data/themes/emo-indifferent.png
new file mode 100644 (file)
index 0000000..254133b
Binary files /dev/null and b/data/themes/emo-indifferent.png differ
diff --git a/data/themes/emo-kiss.png b/data/themes/emo-kiss.png
new file mode 100644 (file)
index 0000000..5eb606d
Binary files /dev/null and b/data/themes/emo-kiss.png differ
diff --git a/data/themes/emo-knowing-grin.png b/data/themes/emo-knowing-grin.png
new file mode 100644 (file)
index 0000000..589b44d
Binary files /dev/null and b/data/themes/emo-knowing-grin.png differ
diff --git a/data/themes/emo-laugh.png b/data/themes/emo-laugh.png
new file mode 100644 (file)
index 0000000..282c620
Binary files /dev/null and b/data/themes/emo-laugh.png differ
diff --git a/data/themes/emo-little-bit-sorry.png b/data/themes/emo-little-bit-sorry.png
new file mode 100644 (file)
index 0000000..fced0e2
Binary files /dev/null and b/data/themes/emo-little-bit-sorry.png differ
diff --git a/data/themes/emo-love-lots.png b/data/themes/emo-love-lots.png
new file mode 100644 (file)
index 0000000..4591fe8
Binary files /dev/null and b/data/themes/emo-love-lots.png differ
diff --git a/data/themes/emo-love.png b/data/themes/emo-love.png
new file mode 100644 (file)
index 0000000..8fd0785
Binary files /dev/null and b/data/themes/emo-love.png differ
diff --git a/data/themes/emo-minimal-smile.png b/data/themes/emo-minimal-smile.png
new file mode 100644 (file)
index 0000000..c005174
Binary files /dev/null and b/data/themes/emo-minimal-smile.png differ
diff --git a/data/themes/emo-not-happy.png b/data/themes/emo-not-happy.png
new file mode 100644 (file)
index 0000000..91b4759
Binary files /dev/null and b/data/themes/emo-not-happy.png differ
diff --git a/data/themes/emo-not-impressed.png b/data/themes/emo-not-impressed.png
new file mode 100644 (file)
index 0000000..8a6901c
Binary files /dev/null and b/data/themes/emo-not-impressed.png differ
diff --git a/data/themes/emo-omg.png b/data/themes/emo-omg.png
new file mode 100644 (file)
index 0000000..8f16f50
Binary files /dev/null and b/data/themes/emo-omg.png differ
diff --git a/data/themes/emo-opensmile.png b/data/themes/emo-opensmile.png
new file mode 100644 (file)
index 0000000..3e37d18
Binary files /dev/null and b/data/themes/emo-opensmile.png differ
diff --git a/data/themes/emo-smile.png b/data/themes/emo-smile.png
new file mode 100644 (file)
index 0000000..082731d
Binary files /dev/null and b/data/themes/emo-smile.png differ
diff --git a/data/themes/emo-sorry.png b/data/themes/emo-sorry.png
new file mode 100644 (file)
index 0000000..757fbc7
Binary files /dev/null and b/data/themes/emo-sorry.png differ
diff --git a/data/themes/emo-squint-laugh.png b/data/themes/emo-squint-laugh.png
new file mode 100644 (file)
index 0000000..0e1850b
Binary files /dev/null and b/data/themes/emo-squint-laugh.png differ
diff --git a/data/themes/emo-surprised.png b/data/themes/emo-surprised.png
new file mode 100644 (file)
index 0000000..0b980c6
Binary files /dev/null and b/data/themes/emo-surprised.png differ
diff --git a/data/themes/emo-suspicious.png b/data/themes/emo-suspicious.png
new file mode 100644 (file)
index 0000000..15bcdc0
Binary files /dev/null and b/data/themes/emo-suspicious.png differ
diff --git a/data/themes/emo-tongue-dangling.png b/data/themes/emo-tongue-dangling.png
new file mode 100644 (file)
index 0000000..eb711ce
Binary files /dev/null and b/data/themes/emo-tongue-dangling.png differ
diff --git a/data/themes/emo-tongue-poke.png b/data/themes/emo-tongue-poke.png
new file mode 100644 (file)
index 0000000..932ef85
Binary files /dev/null and b/data/themes/emo-tongue-poke.png differ
diff --git a/data/themes/emo-uh.png b/data/themes/emo-uh.png
new file mode 100644 (file)
index 0000000..554ca35
Binary files /dev/null and b/data/themes/emo-uh.png differ
diff --git a/data/themes/emo-unhappy.png b/data/themes/emo-unhappy.png
new file mode 100644 (file)
index 0000000..163ae6d
Binary files /dev/null and b/data/themes/emo-unhappy.png differ
diff --git a/data/themes/emo-very-sorry.png b/data/themes/emo-very-sorry.png
new file mode 100644 (file)
index 0000000..97091f2
Binary files /dev/null and b/data/themes/emo-very-sorry.png differ
diff --git a/data/themes/emo-what.png b/data/themes/emo-what.png
new file mode 100644 (file)
index 0000000..a472434
Binary files /dev/null and b/data/themes/emo-what.png differ
diff --git a/data/themes/emo-wink.png b/data/themes/emo-wink.png
new file mode 100644 (file)
index 0000000..ad4553a
Binary files /dev/null and b/data/themes/emo-wink.png differ
diff --git a/data/themes/emo-worried.png b/data/themes/emo-worried.png
new file mode 100644 (file)
index 0000000..b081784
Binary files /dev/null and b/data/themes/emo-worried.png differ
diff --git a/data/themes/emo-wtf.png b/data/themes/emo-wtf.png
new file mode 100644 (file)
index 0000000..5551d8b
Binary files /dev/null and b/data/themes/emo-wtf.png differ
diff --git a/data/themes/flip.xcf.gz b/data/themes/flip.xcf.gz
new file mode 100644 (file)
index 0000000..36aca4d
Binary files /dev/null and b/data/themes/flip.xcf.gz differ
diff --git a/data/themes/flip_0b.png b/data/themes/flip_0b.png
new file mode 100644 (file)
index 0000000..8a6ae9e
Binary files /dev/null and b/data/themes/flip_0b.png differ
diff --git a/data/themes/flip_0t.png b/data/themes/flip_0t.png
new file mode 100644 (file)
index 0000000..72506aa
Binary files /dev/null and b/data/themes/flip_0t.png differ
diff --git a/data/themes/flip_1b.png b/data/themes/flip_1b.png
new file mode 100644 (file)
index 0000000..ed80e8b
Binary files /dev/null and b/data/themes/flip_1b.png differ
diff --git a/data/themes/flip_1t.png b/data/themes/flip_1t.png
new file mode 100644 (file)
index 0000000..6c1fba8
Binary files /dev/null and b/data/themes/flip_1t.png differ
diff --git a/data/themes/flip_2b.png b/data/themes/flip_2b.png
new file mode 100644 (file)
index 0000000..3183b59
Binary files /dev/null and b/data/themes/flip_2b.png differ
diff --git a/data/themes/flip_2t.png b/data/themes/flip_2t.png
new file mode 100644 (file)
index 0000000..3453e3d
Binary files /dev/null and b/data/themes/flip_2t.png differ
diff --git a/data/themes/flip_3b.png b/data/themes/flip_3b.png
new file mode 100644 (file)
index 0000000..2eca7d4
Binary files /dev/null and b/data/themes/flip_3b.png differ
diff --git a/data/themes/flip_3t.png b/data/themes/flip_3t.png
new file mode 100644 (file)
index 0000000..4de9804
Binary files /dev/null and b/data/themes/flip_3t.png differ
diff --git a/data/themes/flip_4b.png b/data/themes/flip_4b.png
new file mode 100644 (file)
index 0000000..23484c9
Binary files /dev/null and b/data/themes/flip_4b.png differ
diff --git a/data/themes/flip_4t.png b/data/themes/flip_4t.png
new file mode 100644 (file)
index 0000000..2029161
Binary files /dev/null and b/data/themes/flip_4t.png differ
diff --git a/data/themes/flip_5b.png b/data/themes/flip_5b.png
new file mode 100644 (file)
index 0000000..8d9312a
Binary files /dev/null and b/data/themes/flip_5b.png differ
diff --git a/data/themes/flip_5t.png b/data/themes/flip_5t.png
new file mode 100644 (file)
index 0000000..df43929
Binary files /dev/null and b/data/themes/flip_5t.png differ
diff --git a/data/themes/flip_6b.png b/data/themes/flip_6b.png
new file mode 100644 (file)
index 0000000..09393e6
Binary files /dev/null and b/data/themes/flip_6b.png differ
diff --git a/data/themes/flip_6t.png b/data/themes/flip_6t.png
new file mode 100644 (file)
index 0000000..3cc4061
Binary files /dev/null and b/data/themes/flip_6t.png differ
diff --git a/data/themes/flip_7b.png b/data/themes/flip_7b.png
new file mode 100644 (file)
index 0000000..9afc419
Binary files /dev/null and b/data/themes/flip_7b.png differ
diff --git a/data/themes/flip_7t.png b/data/themes/flip_7t.png
new file mode 100644 (file)
index 0000000..abe1bc9
Binary files /dev/null and b/data/themes/flip_7t.png differ
diff --git a/data/themes/flip_8b.png b/data/themes/flip_8b.png
new file mode 100644 (file)
index 0000000..2185ee9
Binary files /dev/null and b/data/themes/flip_8b.png differ
diff --git a/data/themes/flip_8t.png b/data/themes/flip_8t.png
new file mode 100644 (file)
index 0000000..718e484
Binary files /dev/null and b/data/themes/flip_8t.png differ
diff --git a/data/themes/flip_9b.png b/data/themes/flip_9b.png
new file mode 100644 (file)
index 0000000..f867aea
Binary files /dev/null and b/data/themes/flip_9b.png differ
diff --git a/data/themes/flip_9t.png b/data/themes/flip_9t.png
new file mode 100644 (file)
index 0000000..5800a4c
Binary files /dev/null and b/data/themes/flip_9t.png differ
diff --git a/data/themes/flip_amb.png b/data/themes/flip_amb.png
new file mode 100644 (file)
index 0000000..e7b3b17
Binary files /dev/null and b/data/themes/flip_amb.png differ
diff --git a/data/themes/flip_amt.png b/data/themes/flip_amt.png
new file mode 100644 (file)
index 0000000..bc6a715
Binary files /dev/null and b/data/themes/flip_amt.png differ
diff --git a/data/themes/flip_b.png b/data/themes/flip_b.png
new file mode 100644 (file)
index 0000000..bb7c7e7
Binary files /dev/null and b/data/themes/flip_b.png differ
diff --git a/data/themes/flip_base.png b/data/themes/flip_base.png
new file mode 100644 (file)
index 0000000..607fba9
Binary files /dev/null and b/data/themes/flip_base.png differ
diff --git a/data/themes/flip_base_shad.png b/data/themes/flip_base_shad.png
new file mode 100644 (file)
index 0000000..0569977
Binary files /dev/null and b/data/themes/flip_base_shad.png differ
diff --git a/data/themes/flip_pmb.png b/data/themes/flip_pmb.png
new file mode 100644 (file)
index 0000000..de14fa5
Binary files /dev/null and b/data/themes/flip_pmb.png differ
diff --git a/data/themes/flip_pmt.png b/data/themes/flip_pmt.png
new file mode 100644 (file)
index 0000000..8a72655
Binary files /dev/null and b/data/themes/flip_pmt.png differ
diff --git a/data/themes/flip_shad.png b/data/themes/flip_shad.png
new file mode 100644 (file)
index 0000000..3d74cea
Binary files /dev/null and b/data/themes/flip_shad.png differ
diff --git a/data/themes/flip_t.png b/data/themes/flip_t.png
new file mode 100644 (file)
index 0000000..74ed50d
Binary files /dev/null and b/data/themes/flip_t.png differ
diff --git a/data/themes/frame_1.png b/data/themes/frame_1.png
new file mode 100644 (file)
index 0000000..fd5645e
Binary files /dev/null and b/data/themes/frame_1.png differ
diff --git a/data/themes/frame_2.png b/data/themes/frame_2.png
new file mode 100644 (file)
index 0000000..0fef1e9
Binary files /dev/null and b/data/themes/frame_2.png differ
diff --git a/data/themes/group_index.png b/data/themes/group_index.png
new file mode 100644 (file)
index 0000000..7df0680
Binary files /dev/null and b/data/themes/group_index.png differ
diff --git a/data/themes/head.png b/data/themes/head.png
new file mode 100644 (file)
index 0000000..905b92c
Binary files /dev/null and b/data/themes/head.png differ
diff --git a/data/themes/hoversel_entry_bg.png b/data/themes/hoversel_entry_bg.png
new file mode 100644 (file)
index 0000000..ec8b31d
Binary files /dev/null and b/data/themes/hoversel_entry_bg.png differ
diff --git a/data/themes/icon_apps.png b/data/themes/icon_apps.png
new file mode 100644 (file)
index 0000000..a3b90c6
Binary files /dev/null and b/data/themes/icon_apps.png differ
diff --git a/data/themes/icon_arrow_down.png b/data/themes/icon_arrow_down.png
new file mode 100644 (file)
index 0000000..899373f
Binary files /dev/null and b/data/themes/icon_arrow_down.png differ
diff --git a/data/themes/icon_arrow_down_left.png b/data/themes/icon_arrow_down_left.png
new file mode 100644 (file)
index 0000000..2f1d2ed
Binary files /dev/null and b/data/themes/icon_arrow_down_left.png differ
diff --git a/data/themes/icon_arrow_down_right.png b/data/themes/icon_arrow_down_right.png
new file mode 100644 (file)
index 0000000..0439e88
Binary files /dev/null and b/data/themes/icon_arrow_down_right.png differ
diff --git a/data/themes/icon_arrow_left.png b/data/themes/icon_arrow_left.png
new file mode 100644 (file)
index 0000000..6651510
Binary files /dev/null and b/data/themes/icon_arrow_left.png differ
diff --git a/data/themes/icon_arrow_right.png b/data/themes/icon_arrow_right.png
new file mode 100644 (file)
index 0000000..58fa68d
Binary files /dev/null and b/data/themes/icon_arrow_right.png differ
diff --git a/data/themes/icon_arrow_up.png b/data/themes/icon_arrow_up.png
new file mode 100644 (file)
index 0000000..46584db
Binary files /dev/null and b/data/themes/icon_arrow_up.png differ
diff --git a/data/themes/icon_arrow_up_left.png b/data/themes/icon_arrow_up_left.png
new file mode 100644 (file)
index 0000000..711bef8
Binary files /dev/null and b/data/themes/icon_arrow_up_left.png differ
diff --git a/data/themes/icon_arrow_up_right.png b/data/themes/icon_arrow_up_right.png
new file mode 100644 (file)
index 0000000..7a9f495
Binary files /dev/null and b/data/themes/icon_arrow_up_right.png differ
diff --git a/data/themes/icon_chat.png b/data/themes/icon_chat.png
new file mode 100644 (file)
index 0000000..1fe8f63
Binary files /dev/null and b/data/themes/icon_chat.png differ
diff --git a/data/themes/icon_clock.png b/data/themes/icon_clock.png
new file mode 100644 (file)
index 0000000..c89ae17
Binary files /dev/null and b/data/themes/icon_clock.png differ
diff --git a/data/themes/icon_close.png b/data/themes/icon_close.png
new file mode 100644 (file)
index 0000000..d0a5166
Binary files /dev/null and b/data/themes/icon_close.png differ
diff --git a/data/themes/icon_delete.png b/data/themes/icon_delete.png
new file mode 100644 (file)
index 0000000..e0a635e
Binary files /dev/null and b/data/themes/icon_delete.png differ
diff --git a/data/themes/icon_edit.png b/data/themes/icon_edit.png
new file mode 100644 (file)
index 0000000..8dcec9e
Binary files /dev/null and b/data/themes/icon_edit.png differ
diff --git a/data/themes/icon_file.png b/data/themes/icon_file.png
new file mode 100644 (file)
index 0000000..371f1d0
Binary files /dev/null and b/data/themes/icon_file.png differ
diff --git a/data/themes/icon_folder.png b/data/themes/icon_folder.png
new file mode 100644 (file)
index 0000000..2ec380a
Binary files /dev/null and b/data/themes/icon_folder.png differ
diff --git a/data/themes/icon_home.png b/data/themes/icon_home.png
new file mode 100644 (file)
index 0000000..a395fff
Binary files /dev/null and b/data/themes/icon_home.png differ
diff --git a/data/themes/icon_left_arrow.png b/data/themes/icon_left_arrow.png
new file mode 100644 (file)
index 0000000..556399e
Binary files /dev/null and b/data/themes/icon_left_arrow.png differ
diff --git a/data/themes/icon_refresh.png b/data/themes/icon_refresh.png
new file mode 100644 (file)
index 0000000..5ea70bf
Binary files /dev/null and b/data/themes/icon_refresh.png differ
diff --git a/data/themes/icon_right_arrow.png b/data/themes/icon_right_arrow.png
new file mode 100644 (file)
index 0000000..6bbb2c6
Binary files /dev/null and b/data/themes/icon_right_arrow.png differ
diff --git a/data/themes/ilist_1.png b/data/themes/ilist_1.png
new file mode 100644 (file)
index 0000000..40a3238
Binary files /dev/null and b/data/themes/ilist_1.png differ
diff --git a/data/themes/ilist_1_h.png b/data/themes/ilist_1_h.png
new file mode 100644 (file)
index 0000000..bd2fd15
Binary files /dev/null and b/data/themes/ilist_1_h.png differ
diff --git a/data/themes/ilist_2.png b/data/themes/ilist_2.png
new file mode 100644 (file)
index 0000000..ee69f15
Binary files /dev/null and b/data/themes/ilist_2.png differ
diff --git a/data/themes/ilist_2_h.png b/data/themes/ilist_2_h.png
new file mode 100644 (file)
index 0000000..6ab252e
Binary files /dev/null and b/data/themes/ilist_2_h.png differ
diff --git a/data/themes/ilist_item_shadow.png b/data/themes/ilist_item_shadow.png
new file mode 100644 (file)
index 0000000..bffa9dc
Binary files /dev/null and b/data/themes/ilist_item_shadow.png differ
diff --git a/data/themes/ilist_item_shadow_h.png b/data/themes/ilist_item_shadow_h.png
new file mode 100644 (file)
index 0000000..fb21bc5
Binary files /dev/null and b/data/themes/ilist_item_shadow_h.png differ
diff --git a/data/themes/leftright.png b/data/themes/leftright.png
new file mode 100644 (file)
index 0000000..8188c19
Binary files /dev/null and b/data/themes/leftright.png differ
diff --git a/data/themes/map_item.png b/data/themes/map_item.png
new file mode 100644 (file)
index 0000000..9e90159
Binary files /dev/null and b/data/themes/map_item.png differ
diff --git a/data/themes/map_item_1.png b/data/themes/map_item_1.png
new file mode 100644 (file)
index 0000000..da9b580
Binary files /dev/null and b/data/themes/map_item_1.png differ
diff --git a/data/themes/map_item_2.png b/data/themes/map_item_2.png
new file mode 100644 (file)
index 0000000..f92ebfa
Binary files /dev/null and b/data/themes/map_item_2.png differ
diff --git a/data/themes/outdent-bottom.png b/data/themes/outdent-bottom.png
new file mode 100644 (file)
index 0000000..2cd49b5
Binary files /dev/null and b/data/themes/outdent-bottom.png differ
diff --git a/data/themes/outdent-top.png b/data/themes/outdent-top.png
new file mode 100644 (file)
index 0000000..b4f891d
Binary files /dev/null and b/data/themes/outdent-top.png differ
diff --git a/data/themes/radio.png b/data/themes/radio.png
new file mode 100644 (file)
index 0000000..f964acd
Binary files /dev/null and b/data/themes/radio.png differ
diff --git a/data/themes/radio2.png b/data/themes/radio2.png
new file mode 100644 (file)
index 0000000..b83e552
Binary files /dev/null and b/data/themes/radio2.png differ
diff --git a/data/themes/radio_base.png b/data/themes/radio_base.png
new file mode 100644 (file)
index 0000000..d219400
Binary files /dev/null and b/data/themes/radio_base.png differ
diff --git a/data/themes/sb_runnerh.png b/data/themes/sb_runnerh.png
new file mode 100644 (file)
index 0000000..a483ce8
Binary files /dev/null and b/data/themes/sb_runnerh.png differ
diff --git a/data/themes/sb_runnerv.png b/data/themes/sb_runnerv.png
new file mode 100644 (file)
index 0000000..cb2da6f
Binary files /dev/null and b/data/themes/sb_runnerv.png differ
diff --git a/data/themes/separator_h.png b/data/themes/separator_h.png
new file mode 100644 (file)
index 0000000..0823fbc
Binary files /dev/null and b/data/themes/separator_h.png differ
diff --git a/data/themes/separator_v.png b/data/themes/separator_v.png
new file mode 100644 (file)
index 0000000..cd1b018
Binary files /dev/null and b/data/themes/separator_v.png differ
diff --git a/data/themes/shad_circ.png b/data/themes/shad_circ.png
new file mode 100644 (file)
index 0000000..e344e5c
Binary files /dev/null and b/data/themes/shad_circ.png differ
diff --git a/data/themes/shadow.png b/data/themes/shadow.png
new file mode 100644 (file)
index 0000000..5dc92cc
Binary files /dev/null and b/data/themes/shadow.png differ
diff --git a/data/themes/shelf_inset.png b/data/themes/shelf_inset.png
new file mode 100644 (file)
index 0000000..bb1989d
Binary files /dev/null and b/data/themes/shelf_inset.png differ
diff --git a/data/themes/sl_bg.png b/data/themes/sl_bg.png
new file mode 100644 (file)
index 0000000..ef88a18
Binary files /dev/null and b/data/themes/sl_bg.png differ
diff --git a/data/themes/sl_bg_over.png b/data/themes/sl_bg_over.png
new file mode 100644 (file)
index 0000000..cca085d
Binary files /dev/null and b/data/themes/sl_bg_over.png differ
diff --git a/data/themes/sl_bt2_0_0.png b/data/themes/sl_bt2_0_0.png
new file mode 100644 (file)
index 0000000..f1270cc
Binary files /dev/null and b/data/themes/sl_bt2_0_0.png differ
diff --git a/data/themes/sl_bt2_0_1.png b/data/themes/sl_bt2_0_1.png
new file mode 100644 (file)
index 0000000..5db1c7c
Binary files /dev/null and b/data/themes/sl_bt2_0_1.png differ
diff --git a/data/themes/sl_bt2_0_2.png b/data/themes/sl_bt2_0_2.png
new file mode 100644 (file)
index 0000000..5c04539
Binary files /dev/null and b/data/themes/sl_bt2_0_2.png differ
diff --git a/data/themes/sl_bt2_1.png b/data/themes/sl_bt2_1.png
new file mode 100644 (file)
index 0000000..3872c8c
Binary files /dev/null and b/data/themes/sl_bt2_1.png differ
diff --git a/data/themes/sl_bt2_2.png b/data/themes/sl_bt2_2.png
new file mode 100644 (file)
index 0000000..061ac29
Binary files /dev/null and b/data/themes/sl_bt2_2.png differ
diff --git a/data/themes/sl_bt_0.png b/data/themes/sl_bt_0.png
new file mode 100644 (file)
index 0000000..8691b19
Binary files /dev/null and b/data/themes/sl_bt_0.png differ
diff --git a/data/themes/sl_bt_1.png b/data/themes/sl_bt_1.png
new file mode 100644 (file)
index 0000000..a29f65c
Binary files /dev/null and b/data/themes/sl_bt_1.png differ
diff --git a/data/themes/sl_bt_2.png b/data/themes/sl_bt_2.png
new file mode 100644 (file)
index 0000000..96bd191
Binary files /dev/null and b/data/themes/sl_bt_2.png differ
diff --git a/data/themes/sl_bt_3.png b/data/themes/sl_bt_3.png
new file mode 100644 (file)
index 0000000..8be95f5
Binary files /dev/null and b/data/themes/sl_bt_3.png differ
diff --git a/data/themes/sl_units.png b/data/themes/sl_units.png
new file mode 100644 (file)
index 0000000..87b4c1d
Binary files /dev/null and b/data/themes/sl_units.png differ
diff --git a/data/themes/slv_bg.png b/data/themes/slv_bg.png
new file mode 100644 (file)
index 0000000..97af4d9
Binary files /dev/null and b/data/themes/slv_bg.png differ
diff --git a/data/themes/slv_bg_over.png b/data/themes/slv_bg_over.png
new file mode 100644 (file)
index 0000000..837a721
Binary files /dev/null and b/data/themes/slv_bg_over.png differ
diff --git a/data/themes/slv_units.png b/data/themes/slv_units.png
new file mode 100644 (file)
index 0000000..d935b3b
Binary files /dev/null and b/data/themes/slv_units.png differ
diff --git a/data/themes/sp_bt_l.png b/data/themes/sp_bt_l.png
new file mode 100644 (file)
index 0000000..31d0d94
Binary files /dev/null and b/data/themes/sp_bt_l.png differ
diff --git a/data/themes/sp_bt_r.png b/data/themes/sp_bt_r.png
new file mode 100644 (file)
index 0000000..bef2c54
Binary files /dev/null and b/data/themes/sp_bt_r.png differ
diff --git a/data/themes/thumb_shadow.png b/data/themes/thumb_shadow.png
new file mode 100644 (file)
index 0000000..8e66670
Binary files /dev/null and b/data/themes/thumb_shadow.png differ
diff --git a/data/themes/tog_base.png b/data/themes/tog_base.png
new file mode 100644 (file)
index 0000000..25b9bc4
Binary files /dev/null and b/data/themes/tog_base.png differ
diff --git a/data/themes/tog_dis_base.png b/data/themes/tog_dis_base.png
new file mode 100644 (file)
index 0000000..7f6865d
Binary files /dev/null and b/data/themes/tog_dis_base.png differ
diff --git a/data/themes/toolbar_sel.png b/data/themes/toolbar_sel.png
new file mode 100644 (file)
index 0000000..4890e3a
Binary files /dev/null and b/data/themes/toolbar_sel.png differ
diff --git a/data/themes/toolbar_separator_v.png b/data/themes/toolbar_separator_v.png
new file mode 100644 (file)
index 0000000..cb2da6f
Binary files /dev/null and b/data/themes/toolbar_separator_v.png differ
diff --git a/data/themes/tooltip-base.png b/data/themes/tooltip-base.png
new file mode 100644 (file)
index 0000000..3ab8e0f
Binary files /dev/null and b/data/themes/tooltip-base.png differ
diff --git a/data/themes/tooltip-corner-bottom-left-tip.png b/data/themes/tooltip-corner-bottom-left-tip.png
new file mode 100644 (file)
index 0000000..f60787b
Binary files /dev/null and b/data/themes/tooltip-corner-bottom-left-tip.png differ
diff --git a/data/themes/tooltip-corner-bottom-right-tip.png b/data/themes/tooltip-corner-bottom-right-tip.png
new file mode 100644 (file)
index 0000000..4d715f3
Binary files /dev/null and b/data/themes/tooltip-corner-bottom-right-tip.png differ
diff --git a/data/themes/tooltip-corner-top-left-tip.png b/data/themes/tooltip-corner-top-left-tip.png
new file mode 100644 (file)
index 0000000..3f74c58
Binary files /dev/null and b/data/themes/tooltip-corner-top-left-tip.png differ
diff --git a/data/themes/tooltip-corner-top-right-tip.png b/data/themes/tooltip-corner-top-right-tip.png
new file mode 100644 (file)
index 0000000..c9dbaa2
Binary files /dev/null and b/data/themes/tooltip-corner-top-right-tip.png differ
diff --git a/data/themes/tooltip-edge-bottom-tip.png b/data/themes/tooltip-edge-bottom-tip.png
new file mode 100644 (file)
index 0000000..49fd2b0
Binary files /dev/null and b/data/themes/tooltip-edge-bottom-tip.png differ
diff --git a/data/themes/tooltip-edge-left-tip.png b/data/themes/tooltip-edge-left-tip.png
new file mode 100644 (file)
index 0000000..6cf071e
Binary files /dev/null and b/data/themes/tooltip-edge-left-tip.png differ
diff --git a/data/themes/tooltip-edge-right-tip.png b/data/themes/tooltip-edge-right-tip.png
new file mode 100644 (file)
index 0000000..cd541a6
Binary files /dev/null and b/data/themes/tooltip-edge-right-tip.png differ
diff --git a/data/themes/tooltip-edge-top-tip.png b/data/themes/tooltip-edge-top-tip.png
new file mode 100644 (file)
index 0000000..a341a21
Binary files /dev/null and b/data/themes/tooltip-edge-top-tip.png differ
diff --git a/data/themes/up.png b/data/themes/up.png
new file mode 100644 (file)
index 0000000..f8697a1
Binary files /dev/null and b/data/themes/up.png differ
diff --git a/data/themes/updown.png b/data/themes/updown.png
new file mode 100644 (file)
index 0000000..549960c
Binary files /dev/null and b/data/themes/updown.png differ
diff --git a/doc/.cvsignore b/doc/.cvsignore
new file mode 100644 (file)
index 0000000..cc370ed
--- /dev/null
@@ -0,0 +1,3 @@
+html
+latex
+man
diff --git a/doc/Doxyfile b/doc/Doxyfile
new file mode 100644 (file)
index 0000000..d7b9da6
--- /dev/null
@@ -0,0 +1,139 @@
+PROJECT_NAME           = Elementary
+PROJECT_NUMBER         =
+OUTPUT_DIRECTORY       = .
+INPUT                  = elementary.dox ../src/lib
+IMAGE_PATH             = img
+OUTPUT_LANGUAGE        = English
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = head.html
+HTML_FOOTER            = foot.html
+HTML_STYLESHEET        = e.css
+HTML_ALIGN_MEMBERS     = YES
+ENUM_VALUES_PER_LINE   = 1
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = YES
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = NO
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = YES
+HIDE_FRIEND_COMPOUNDS  = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = NO
+SHOW_INCLUDE_FILES     = NO
+JAVADOC_AUTOBRIEF      = YES
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 2
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES                = 
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SHOW_USED_FILES        = NO
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+FILE_PATTERNS          =
+RECURSIVE              = NO
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 2
+IGNORE_PREFIX          = 
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+GENERATE_MAN           = YES
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = YES
+GENERATE_XML           = NO
+XML_SCHEMA             = 
+XML_DTD                = 
+GENERATE_AUTOGEN_DEF   = NO
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = YES
+SEARCH_INCLUDES        = NO
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = __UNUSED__=
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+CLASS_DIAGRAMS         = NO
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = NO
+COLLABORATION_GRAPH    = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = NO
+INCLUDED_BY_GRAPH      = NO
+GRAPHICAL_HIERARCHY    = NO
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 512
+MAX_DOT_GRAPH_HEIGHT   = 512
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+SEARCHENGINE           = NO
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644 (file)
index 0000000..98c0866
--- /dev/null
@@ -0,0 +1,32 @@
+MAINTAINERCLEANFILES = Makefile.in elementary.dox
+
+.PHONY: doc
+
+PACKAGE_DOCNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc
+
+if EFL_BUILD_DOC
+
+doc-clean:
+       rm -rf html/ latex/ man/ xml/ $(PACKAGE_DOCNAME).tar*
+
+doc: all doc-clean
+       $(efl_doxygen)
+       cp img/* html/
+       rm -rf $(PACKAGE_DOCNAME).tar*
+       mkdir -p $(PACKAGE_DOCNAME)/doc
+       cp -R html/ latex/ man/ $(PACKAGE_DOCNAME)/doc
+       tar cf $(PACKAGE_DOCNAME).tar $(PACKAGE_DOCNAME)/
+       bzip2 -9 $(PACKAGE_DOCNAME).tar
+       rm -rf $(PACKAGE_DOCNAME)/
+       mv $(PACKAGE_DOCNAME).tar.bz2 $(top_srcdir)
+
+clean-local: doc-clean
+
+else
+
+doc:
+       @echo "Documentation not built. Run ./configure --help"
+
+endif
+
+EXTRA_DIST = Doxyfile $(wildcard img/*.*) e.css head.html foot.html elementary.dox.in
diff --git a/doc/e.css b/doc/e.css
new file mode 100644 (file)
index 0000000..2dd6b44
--- /dev/null
+++ b/doc/e.css
@@ -0,0 +1,273 @@
+/*
+    Author:
+        Andres Blanc <andresblanc@gmail.com>
+       DaveMDS Andreoli <dave@gurumeditation.it>
+
+    Supported Browsers:
+        ie7, opera9, konqueror4 and firefox3
+
+        Please use a different file for ie6, ie5, etc. hacks.
+*/
+
+
+/* Necessary to place the footer at the bottom of the page */
+html, body {
+       height: 100%;
+       margin: 0px;
+       padding: 0px;
+}
+
+#container {
+       min-height: 100%;
+       height: auto !important;
+       height: 100%;
+       margin: 0 auto -53px;
+}
+
+#footer, #push {
+       height: 53px;
+}
+
+
+* html #container {
+       height: 100%;
+}
+
+/* Prevent floating elements overflowing containers */
+.clear {
+       clear: both;
+       width: 0px;
+       height: 0px;
+}
+
+/* Flexible & centered layout from 750 to 960 pixels */
+.layout {
+       max-width: 960px;
+       min-width: 760px;
+       margin-left: auto;
+       margin-right: auto;
+}
+
+body {
+       /*font-family: Lucida Grande, Helvetica, sans-serif;*/
+       font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif
+}
+
+/* Prevent design overflowing the viewport in small resolutions */
+#container {
+       padding-right: 17px;
+       padding-left: 17px;
+       background-image: url(head_bg.png);
+       background-repeat: repeat-x;
+}
+
+/****************************/
+/* Top main menu            */
+/****************************/
+#header_logo {
+   background-image        : url(logo.png);
+   width                   : 61px;
+}
+
+#header_logo a {
+   position                : absolute;
+   border                  : 0px;
+   background-color        : transparent;
+   top                     : 0px;
+   width                   : 60px;
+   height                  : 60px;
+}
+
+#header_menu {
+   background-image        : url(header_menu_background.png);
+   font                    : normal 10pt verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif;
+   text-align              : right;
+}
+
+#header_last {
+   background-image        : url(header_menu_background_last.png);
+   width                   : 15px;
+}
+
+td.nav_passive {
+   background              : url(header_menu_unselected_background.png) 0 0 no-repeat;
+   height                  : 63px;
+   font-family             : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif;
+   font-size               : 11px;
+   padding                 : 20px 10px 20px 10px;
+   vertical-align          : middle;
+}
+
+td.nav_active {
+   background              : url(header_menu_current_background.png) 0 0 no-repeat;
+   height                  : 63px;
+   color                   : #646464;
+   font-family             : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif;
+   font-size               : 11px;
+   font-weight             : bold;
+   padding                 : 20px 10px 20px 10px;
+   vertical-align          : middle;
+}
+
+#header_menu a {
+   display                 : block;
+   text-decoration         : none;
+   cursor                  : pointer;
+   color                   : #cdcdcd;
+}
+
+
+
+#header {
+       width: 100%;
+       height: 102px;
+}
+
+#header h1 {
+       width: 63px;
+       height: 63px;
+       position: absolute;
+       margin: 0px;
+}
+
+#header h1 span {
+       display: none;
+}
+
+#header h2 {
+       display: none;
+}
+
+/* .menu-container is used to set properties common to .menu and .submenu */
+#header .menu-container {
+}
+
+#header .menu-container ul {
+       list-style-type: none;
+       list-style-position: inside;
+       margin: 0;
+}
+
+#header .menu-container li {
+       display: block;
+       float: right;
+}
+
+#header .menu {
+       height: 63px;
+       display: block;
+       background-image: url(menu_bg.png);
+       background-repeat: repeat-x;
+}
+
+#header .menu ul {
+       height: 100%;
+       display: block;
+       background-image: url(menu_bg_last.png);
+       background-repeat: no-repeat;
+       background-position: top right;
+       padding-right: 17px;
+}
+
+#header .menu li {
+       height: 100%;
+       text-align: center;
+       background-image: url(menu_bg_unsel.png);
+       background-repeat: no-repeat;
+}
+
+#header .menu a {
+       height: 100%;
+       display: block;
+       color: #cdcdcd;
+       text-decoration: none;
+       font-size: 10pt;
+       line-height: 59px;
+       text-align: center;
+       padding: 0px 15px 0px 15px;
+}
+
+#header .menu li:hover {
+       background-image: url(menu_bg_hover.png);
+       background-repeat: no-repeat;
+}
+
+#header .menu li:hover a {
+       color: #FFFFFF;
+}
+
+#header .menu li.current {
+       background-image: url(menu_bg_current.png);
+       background-repeat: no-repeat;
+}
+
+#header .menu li.current a {
+       color: #646464;
+}
+
+
+/* Hide all the submenus but the current */
+#header .submenu ul {
+       display: none;
+}
+
+#header .submenu .current {
+       display: block;
+}
+
+#header .submenu {
+       font: bold 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif;
+       margin-top: 10px;
+}
+
+#header .submenu a {
+       color: #888888;
+       text-decoration: none;
+       font-size: 0.9em;
+       line-height: 15px;
+       padding:0px 5px 0px 5px;
+}
+
+#header .submenu a:hover {
+       color: #444444;
+}
+
+#header .submenu li {
+       border-left: 1px solid #DDDDDD;
+}
+
+#header .submenu li:last-child {
+       border-left: 0;
+}
+
+#header .doxytitle {
+       position: absolute;
+       font-size: 1.8em;
+       font-weight: bold;
+       color: #444444;
+       line-height: 35px;
+}
+
+#header small {
+       font-size: 0.4em;
+}
+
+#footer {
+       background-image: url(foot_bg.png);
+       width: 100%;
+}
+
+#footer table {
+       width: 100%;
+       text-align: center;
+       white-space: nowrap;
+       padding: 5px 30px 5px 30px;
+       font-size: 0.8em;
+       font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif;
+       color: #888888;
+}
+
+#footer td.copyright {
+       width: 100%;
+}
+
diff --git a/doc/elementary.dox.in b/doc/elementary.dox.in
new file mode 100644 (file)
index 0000000..f91c12e
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+@file elementary.dox
+@brief Elementary Widget Library
+*/
+
+/**
+@mainpage Elementary
+@image html  elementary.png
+@version @PACKAGE_VERSION@
+@author Carsten Haitzler <raster@rasterman.com>
+@author Gustavo Sverzut Barbieri <barbieri@profusion.mobi>
+@author Cedric Bail <cedric.bail@free.fr>
+@author Vincent Torri <vtorri@univ-evry.fr>
+@author Daniel Kolesa <quaker66@gmail.com>
+@author Jaime Thomas <avi.thomas@gmail.com>
+@author Swisscom - http://www.swisscom.ch/
+@author Christopher Michael <devilhorns@comcast.net>
+@author Marco Trevisan (Treviño) <mail@3v1n0.net>
+@author Michael Bouchaud <michael.bouchaud@gmail.com>
+@author Jonathan Atton (Watchwolf) <jonathan.atton@gmail.com>
+@author Brian Wang <brian.wang.0721@gmail.com>
+@author Mike Blumenkrantz (zmike) <mike@zentific.com>
+@author Samsung Electronics <tbd>
+@author Samsung SAIT <tbd>
+@author Brett Nash <nash@nash.id.au>
+@author Bruno Dilly <bdilly@profusion.mobi>
+@author Rafael Fonseca <rfonseca@profusion.mobi>
+@author Chuneon Park <chuneon.park@samsung.com>
+@author Woohyun Jung <wh0705.jung@samsung.com>
+@author Jaehwan Kim <jae.hwan.kim@samsung.com>
+@author Wonguk Jeong <wonguk.jeong@samsung.com>
+@author Leandro A. F. Pereira <leandro@profusion.mobi>
+@author Helen Fornazier <helen.fornazier@profusion.mobi>
+@author Gustavo Lima Chaves <glima@profusion.mobi>
+@author Fabiano Fidêncio <fidencio@profusion.mobi>
+@author Tiago Falcão <tiago@profusion.mobi>
+@author Otavio Pontes <otavio@profusion.mobi>
+@author Viktor Kojouharov <vkojouharov@gmail.com>
+@author Daniel Juyung Seo (SeoZ) <juyung.seo@samsung.com> <seojuyung2@gmail.com>
+@date 2008-2010
+
+@section intro What is Elementary?
+
+This is a VERY SIMPLE toolkit. It is not meant for writing extensive desktop
+applications (yet). Small simple ones with simple needs.
+
+It is meant to make the programmers work almost brainless but give them lots
+of flexibility.
+
+License: LGPL v2 (see COPYING in the base of Elementary's source). This
+applies to all files in the source here.
+
+Acknowledgements: There is a lot that goes into making a widget set, and
+they don't happen out of nothing. It's like trying to make everyone
+everywhere happy, regardless of age, gender, race or nationality - and
+that is really tough. So thanks to people and organisations behind this,
+aslisted in the Authors section above.
+
+@verbatim
+Pants
+@endverbatim
+*/
diff --git a/doc/foot.html b/doc/foot.html
new file mode 100644 (file)
index 0000000..d43cf8f
--- /dev/null
@@ -0,0 +1,18 @@
+ <div id="push"></div>
+ </div> <!-- #content -->
+  </div> <!-- .layout -->
+ </div> <!-- #container -->
+  <div id="footer">
+    <table><tr>
+      <td class="copyright">Copyright &copy;$year Enlightenment</td>
+      <td class="generated">Docs generated $datetime</td>
+    </tr></table>
+  </div>
+
+
+</body>
+</html>
diff --git a/doc/head.html b/doc/head.html
new file mode 100644 (file)
index 0000000..7e20e6d
--- /dev/null
@@ -0,0 +1,68 @@
+<html>
+<head>
+    <title>$title</title>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8">
+    <meta name="author" content="Andres Blanc" >
+    
+    <link rel="icon" href="img/favicon.png" type="image/x-icon">
+    <link rel="shortcut icon" href="img/favicon.png" type="image/x-icon">
+    <link rel="icon" href="img/favicon.png" type="image/ico">
+    <link rel="shortcut icon" href="img/favicon.png" type="image/ico">
+
+    <link rel="stylesheet" type="text/css" href="e.css">
+    <link rel="stylesheet" type="text/css" href="edoxy.css">
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="header">
+<div class="layout">
+    
+    <h1><span>Enlightenment</span></h1>
+    <h2><span>Beauty at your fingertips</span></h2>
+
+    <table cellspacing="0" cellpadding="0" width="100%"><tr>
+      <td id="header_logo">
+        <a href="http://www.enlightenment.org"></a>
+      </td>
+      <td id="header_menu">
+        <table cellspacing="0" cellpadding="0" align="right"><tr>
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=home">Home</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=news">News</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=about">About</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=download">Download</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=support">Support</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=contribute">Contribute</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=contact">Contact</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://trac.enlightenment.org/e">Tracker</a></td>
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=docs">Docs</a></td> 
+        </tr></table>          
+      </td>
+      <td id="header_last"></td>
+    </tr></table>
+
+    <div class="doxytitle">
+        $projectname Documentation <small>at $date</small>
+    </div>
+
+    <div class="menu-container">
+        <div class="submenu">
+            <ul class="current">
+                <li><a href="files.html">Files</a></li>
+                <li><a href="globals.html">Globals</a></li>
+                <li><a href="Elementary_8h.html">API Reference</a></li>
+                <li><a href="modules.html">Modules</a></li>
+               <li class="current"><a  href="index.html">Main Page</a></li>
+            </ul>
+        </div>
+    </div>
+
+
+    <div class="clear"></div>
+</div>
+</div>
+
+<div id="content">
+<div class="layout">
diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css
new file mode 100644 (file)
index 0000000..311ca23
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * This file contain a custom doxygen style to match e.org graphics
+ */
+
+
+
+/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+       font-family: Geneva, Arial, Helvetica, sans-serif;
+}*/ 
+BODY, TD {
+       font-size: 12px;
+}
+H1 {
+       text-align: center;
+       font-size: 160%;
+}
+H2 {
+       font-size: 120%;
+}
+H3 {
+       font-size: 100%;
+}
+CAPTION { 
+       font-weight: bold 
+}
+DIV.qindex {
+       width: 100%;
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       padding: 2px;
+       line-height: 140%;
+}
+DIV.navpath {
+       width: 100%;
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       padding: 2px;
+       line-height: 140%;
+}
+DIV.navtab {
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+TD.navtab {
+       font-size: 70%;
+}
+A.qindex {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D;
+}
+A.qindex:visited {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D
+}
+A.qindex:hover {
+       text-decoration: none;
+       background-color: #ddddff;
+}
+A.qindexHL {
+       text-decoration: none;
+       font-weight: bold;
+       background-color: #6666cc;
+       color: #ffffff;
+       border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+       text-decoration: none;
+       background-color: #6666cc;
+       color: #ffffff;
+}
+A.qindexHL:visited { 
+       text-decoration: none; 
+       background-color: #6666cc; 
+       color: #ffffff 
+}
+A.el { 
+       text-decoration: none; 
+       font-weight: bold 
+}
+A.elRef { 
+       font-weight: bold 
+}
+A.code:link { 
+       text-decoration: none; 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.code:visited { 
+       text-decoration: none; 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.codeRef:link { 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.codeRef:visited { 
+       font-weight: normal; 
+       color: #0000FF
+}
+A:hover, A:visited:hover { 
+       text-decoration: none;  
+       /* background-color: #f2f2ff; */
+       color: #000055;
+}
+A.anchor {
+       color: #000;
+}
+DL.el { 
+       margin-left: -1cm 
+}
+.fragment {
+       font-family: monospace, fixed;
+       font-size: 95%;
+}
+PRE.fragment {
+       border: 1px solid #CCCCCC;
+       background-color: #f5f5f5;
+       margin-top: 4px;
+       margin-bottom: 4px;
+       margin-left: 2px;
+       margin-right: 8px;
+       padding-left: 6px;
+       padding-right: 6px;
+       padding-top: 4px;
+       padding-bottom: 4px;
+}
+DIV.ah { 
+       background-color: black; 
+       font-weight: bold; 
+       color: #ffffff; 
+       margin-bottom: 3px; 
+       margin-top: 3px 
+}
+
+DIV.groupHeader {
+       margin-left: 16px;
+       margin-top: 12px;
+       margin-bottom: 6px;
+       font-weight: bold;
+}
+DIV.groupText { 
+       margin-left: 16px; 
+       font-style: italic; 
+       font-size: 90% 
+}
+/*BODY {
+       background: white;
+       color: black;
+       margin-right: 20px;
+       margin-left: 20px;
+}*/
+TD.indexkey {
+       background-color: #e8eef2;
+       font-weight: bold;
+       padding-right  : 10px;
+       padding-top    : 2px;
+       padding-left   : 10px;
+       padding-bottom : 2px;
+       margin-left    : 0px;
+       margin-right   : 0px;
+       margin-top     : 2px;
+       margin-bottom  : 2px;
+       border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+       background-color: #e8eef2;
+       font-style: italic;
+       padding-right  : 10px;
+       padding-top    : 2px;
+       padding-left   : 10px;
+       padding-bottom : 2px;
+       margin-left    : 0px;
+       margin-right   : 0px;
+       margin-top     : 2px;
+       margin-bottom  : 2px;
+       border: 1px solid #CCCCCC;
+}
+TR.memlist {
+       background-color: #f0f0f0; 
+}
+P.formulaDsp { 
+       text-align: center; 
+}
+IMG.formulaDsp {
+}
+IMG.formulaInl { 
+       vertical-align: middle; 
+}
+SPAN.keyword       { color: #008000 }
+SPAN.keywordtype   { color: #604020 }
+SPAN.keywordflow   { color: #e08000 }
+SPAN.comment       { color: #800000 }
+SPAN.preprocessor  { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral   { color: #008080 }
+SPAN.vhdldigit     { color: #ff00ff }
+SPAN.vhdlchar      { color: #000000 }
+SPAN.vhdlkeyword   { color: #700070 }
+SPAN.vhdllogic     { color: #ff0000 }
+
+.mdescLeft {
+       padding: 0px 8px 4px 8px;
+       font-size: 80%;
+       font-style: italic;
+       background-color: #FAFAFA;
+       border-top: 1px none #E0E0E0;
+       border-right: 1px none #E0E0E0;
+       border-bottom: 1px none #E0E0E0;
+       border-left: 1px none #E0E0E0;
+       margin: 0px;
+}
+.mdescRight {
+        padding: 0px 8px 4px 8px;
+       font-size: 80%;
+       font-style: italic;
+       background-color: #FAFAFA;
+       border-top: 1px none #E0E0E0;
+       border-right: 1px none #E0E0E0;
+       border-bottom: 1px none #E0E0E0;
+       border-left: 1px none #E0E0E0;
+       margin: 0px;
+}
+.memItemLeft {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memItemRight {
+       padding: 1px 8px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplItemLeft {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: none;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplItemRight {
+       padding: 1px 8px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: none;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplParams {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       color: #606060;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.search { 
+       color: #003399;
+       font-weight: bold;
+}
+FORM.search {
+       margin-bottom: 0px;
+       margin-top: 0px;
+}
+INPUT.search { 
+       font-size: 75%;
+       color: #000080;
+       font-weight: normal;
+       background-color: #e8eef2;
+}
+TD.tiny { 
+       font-size: 75%;
+}
+a {
+       color: #1A41A8;
+}
+a:visited {
+       color: #2A3798;
+}
+.dirtab { 
+       padding: 4px;
+       border-collapse: collapse;
+       border: 1px solid #84b0c7;
+}
+TH.dirtab { 
+       background: #e8eef2;
+       font-weight: bold;
+}
+HR { 
+       height: 1px;
+       border: none;
+       border-top: 1px solid black;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+       font-size: 80%;
+       color: #606060;
+       font-weight: normal;
+       margin-left: 3px;
+} 
+.memnav { 
+       background-color: #eeeeee;
+       border: 1px solid #dddddd;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+.memitem {
+       padding: 4px;
+       background-color: #eeeeee;
+       border-width: 1px;
+       border-style: solid;
+       border-color: #dddddd;
+       -moz-border-radius: 4px 4px 4px 4px;
+}
+.memname {
+       white-space: nowrap;
+       font-weight: bold;
+        color: #ffffff;
+}
+.memdoc{
+       padding-left: 10px;
+}
+.memproto {
+       background-color: #111111;
+       width: 100%;
+       border-width: 1px;
+       border-style: solid;
+       border-color: #000000;
+       font-weight: bold;
+       -moz-border-radius: 4px 4px 4px 4px;
+}
+.paramkey {
+       text-align: right;
+       color: #ffffff;
+}
+.paramtype {
+       white-space: nowrap;
+       color: #aaaaaa;
+}
+.paramname {
+       color: #ff0000;
+       font-style: italic;
+       white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+       font-family: sans-serif;
+       margin:0.5em;
+}
+/* these are for tree view when used as main index */
+.directory { 
+       font-size: 9pt; 
+       font-weight: bold; 
+}
+.directory h3 { 
+       margin: 0px; 
+       margin-top: 1em; 
+       font-size: 11pt; 
+}
+
+/* The following two styles can be used to replace the root node title */
+/* with an image of your choice.  Simply uncomment the next two styles, */
+/* specify the name of your image and be sure to set 'height' to the */
+/* proper pixel height of your image. */
+
+/* .directory h3.swap { */
+/*     height: 61px; */
+/*     background-repeat: no-repeat; */
+/*     background-image: url("yourimage.gif"); */
+/* } */
+/* .directory h3.swap span { */
+/*     display: none; */
+/* } */
+
+.directory > h3 { 
+       margin-top: 0; 
+}
+.directory p { 
+       margin: 0px; 
+       white-space: nowrap; 
+}
+.directory div { 
+       display: none; 
+       margin: 0px; 
+}
+.directory img { 
+       vertical-align: -30%; 
+}
+/* these are for tree view when not used as main index */
+.directory-alt { 
+       font-size: 100%; 
+       font-weight: bold; 
+}
+.directory-alt h3 { 
+       margin: 0px; 
+       margin-top: 1em; 
+       font-size: 11pt; 
+}
+.directory-alt > h3 { 
+       margin-top: 0; 
+}
+.directory-alt p { 
+       margin: 0px; 
+       white-space: nowrap; 
+}
+.directory-alt div { 
+       display: none; 
+       margin: 0px; 
+}
+.directory-alt img { 
+       vertical-align: -30%; 
+}
+
diff --git a/doc/img/elementary.png b/doc/img/elementary.png
new file mode 100644 (file)
index 0000000..7975489
Binary files /dev/null and b/doc/img/elementary.png differ
diff --git a/doc/img/foot_bg.png b/doc/img/foot_bg.png
new file mode 100644 (file)
index 0000000..b24f3a4
Binary files /dev/null and b/doc/img/foot_bg.png differ
diff --git a/doc/img/head_bg.png b/doc/img/head_bg.png
new file mode 100644 (file)
index 0000000..081dc13
Binary files /dev/null and b/doc/img/head_bg.png differ
diff --git a/doc/img/header_menu_background.png b/doc/img/header_menu_background.png
new file mode 100644 (file)
index 0000000..e978743
Binary files /dev/null and b/doc/img/header_menu_background.png differ
diff --git a/doc/img/header_menu_background_last.png b/doc/img/header_menu_background_last.png
new file mode 100644 (file)
index 0000000..88c116c
Binary files /dev/null and b/doc/img/header_menu_background_last.png differ
diff --git a/doc/img/header_menu_current_background.png b/doc/img/header_menu_current_background.png
new file mode 100644 (file)
index 0000000..de97c92
Binary files /dev/null and b/doc/img/header_menu_current_background.png differ
diff --git a/doc/img/header_menu_unselected_background.png b/doc/img/header_menu_unselected_background.png
new file mode 100644 (file)
index 0000000..50e5fd8
Binary files /dev/null and b/doc/img/header_menu_unselected_background.png differ
diff --git a/doc/img/logo.png b/doc/img/logo.png
new file mode 100644 (file)
index 0000000..b3884a5
Binary files /dev/null and b/doc/img/logo.png differ
diff --git a/elementary.pc.in b/elementary.pc.in
new file mode 100644 (file)
index 0000000..cb3ea4b
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: elementary
+Description: Mobile device touchscreen widget library
+@pkgconfig_requires_private@: @requirement_elm@
+Version: @VERSION@
+Libs: -L${libdir} -lelementary
+Libs.private: @dlopen_libs@ @my_libs@
+Cflags: -I${includedir}/elementary-@VMAJ@
diff --git a/elementary.spec.in b/elementary.spec.in
new file mode 100644 (file)
index 0000000..e255c54
--- /dev/null
@@ -0,0 +1,102 @@
+%define _missing_doc_files_terminate_build 0
+
+%{!?_rel:%{expand:%%global _rel 0.r%(svnversion | sed 's/[^0-9].*$//' || echo 0000)}}
+
+Summary: EFL toolkit for small touchscreens
+Name: @PACKAGE@
+Version: @VERSION@
+Release: %{_rel}
+License: Lesser GPL
+Group: System Environment/Libraries
+URL: http://trac.enlightenment.org/e/wiki/Elementary
+Source: %{name}-%{version}.tar.gz
+Packager: %{?_packager:%{_packager}}%{!?_packager:Rui Miguel Silva Seabra <rms@1407.org>}
+Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)}
+Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
+#BuildSuggests: xorg-x11-devel, vim-enhanced
+BuildRequires: evas-devel
+Requires:  evas
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+Elementary is a widget set. It is a new-style of widget set much more canvas
+object based than anything else. Why not ETK? Why not EWL? Well they both
+tend to veer away from the core of Evas, Ecore and Edje a lot to build their
+own worlds. Also I wanted something focused on embedded devices -
+specifically small touchscreens. Unlike GTK+ and Qt, 75% of the "widget set"
+is already embodied in a common core - Ecore, Edje, Evas etc. So this
+fine-grained library splitting means all of this is shared, just a new
+widget "personality" is on top. And that is... Elementary, my dear watson.
+Elementary.
+
+%package devel
+Summary: Elementary headers, static libraries, documentation and test programs
+Group: System Environment/Libraries
+Requires: %{name} = %{version}, %{name}-bin = %{version}
+Requires: evas-devel
+
+%description devel
+Headers, static libraries, test programs and documentation for Elementary
+
+%package bin
+Summary: Elementary file compiler/decompiler suite
+Group: System Environment/Libraries
+Requires: %{name} = %{version}
+Requires: elementary
+
+%description bin
+Elmementary programs
+
+%prep
+%setup -q
+
+%build
+%{configure} --prefix=%{_prefix}
+%{__make} %{?_smp_mflags} %{?mflags}
+
+%install
+%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install
+test -x `which doxygen` && sh gendoc || :
+
+%post
+/sbin/ldconfig || :
+
+%postun
+/sbin/ldconfig || :
+
+%clean
+test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-, root, root)
+%doc AUTHORS COPYING README
+%{_libdir}/libelementary*.so.*
+
+%files devel
+%defattr(-, root, root)
+%doc doc/html
+%{_libdir}/*.so
+%{_libdir}/*.la
+%{_libdir}/*.a
+%{_libdir}/edje/*.so
+%{_libdir}/edje/*.la
+%{_libdir}/elementary/modules/test_entry/*/module.*
+%{_libdir}/pkgconfig/*
+%{_includedir}/*.h
+%{_includedir}/elementary/*.h
+
+%files bin
+%defattr(-, root, root)
+%{_bindir}/*
+%{_datadir}/applications/*.desktop
+%{_datadir}/elementary/config/*.cfg
+%{_datadir}/elementary/config/default/*
+%{_datadir}/elementary/config/illume/*
+%{_datadir}/elementary/config/standard/*
+%{_datadir}/elementary/edje_externals/*
+%{_datadir}/elementary/images/*
+%{_datadir}/elementary/objects/*
+%{_datadir}/elementary/themes/*
+%{_datadir}/icons/elementary.png
+
+%changelog
diff --git a/m4/ac_attribute.m4 b/m4/ac_attribute.m4
new file mode 100644 (file)
index 0000000..23479a9
--- /dev/null
@@ -0,0 +1,47 @@
+dnl Copyright (C) 2004-2008 Kim Woelders
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+dnl Originally snatched from somewhere...
+
+dnl Macro for checking if the compiler supports __attribute__
+
+dnl Usage: AC_C___ATTRIBUTE__
+dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__
+dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is
+dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused))
+dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is
+dnl defined to nothing.
+
+AC_DEFUN([AC_C___ATTRIBUTE__],
+[
+
+AC_MSG_CHECKING([for __attribute__])
+
+AC_CACHE_VAL([ac_cv___attribute__],
+   [AC_TRY_COMPILE(
+       [
+#include <stdlib.h>
+
+int func(int x);
+int foo(int x __attribute__ ((unused)))
+{
+   exit(1);
+}
+       ],
+       [],
+       [ac_cv___attribute__="yes"],
+       [ac_cv___attribute__="no"]
+    )])
+
+AC_MSG_RESULT($ac_cv___attribute__)
+
+if test "x${ac_cv___attribute__}" = "xyes" ; then
+   AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__])
+   AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused])
+  else
+    AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused])
+fi
+
+])
+
+dnl End of ac_attribute.m4
diff --git a/m4/efl_binary.m4 b/m4/efl_binary.m4
new file mode 100644 (file)
index 0000000..c774688
--- /dev/null
@@ -0,0 +1,71 @@
+dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if a binary is built or not
+
+dnl Usage: EFL_ENABLE_BIN(binary)
+dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _)
+dnl Define have_binary (- is transformed into _)
+dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _)
+
+AC_DEFUN([EFL_ENABLE_BIN],
+[
+
+m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl
+m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl
+
+have_[]m4_defn([DOWN])="yes"
+
+dnl configure option
+
+AC_ARG_ENABLE([$1],
+   [AC_HELP_STRING([--disable-$1], [disable building of ]DOWN)],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       have_[]m4_defn([DOWN])="yes"
+    else
+       have_[]m4_defn([DOWN])="no"
+    fi
+   ])
+
+AC_MSG_CHECKING([whether to build ]DOWN[ binary])
+AC_MSG_RESULT([$have_[]m4_defn([DOWN])])
+
+if test "x$have_[]m4_defn([DOWN])" = "xyes"; then
+   UP[]_PRG=DOWN[${EXEEXT}]
+fi
+
+AC_SUBST(UP[]_PRG)
+
+AM_CONDITIONAL(BUILD_[]UP, test "x$have_[]m4_defn([DOWN])" = "xyes")
+
+AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$2], [$3])
+
+])
+
+
+dnl Macro that check if a binary is built or not
+
+dnl Usage: EFL_WITH_BIN(package, binary, default_value)
+dnl Call AC_SUBST(_binary) (_binary is the lowercase of binary, - being transformed into _ by default, or the value set by the user)
+
+AC_DEFUN([EFL_WITH_BIN],
+[
+
+m4_pushdef([DOWN], m4_translit([[$2]], [-A-Z], [_a-z]))dnl
+
+dnl configure option
+
+AC_ARG_WITH([$2],
+   [AC_HELP_STRING([--with-$2=PATH], [specify a specific path to ]DOWN[ @<:@default=$3@:>@])],
+   [_efl_with_binary=${withval}],
+   [_efl_with_binary=$(pkg-config --variable=prefix $1)/bin/$3])
+
+DOWN=${_efl_with_binary}
+AC_MSG_NOTICE(DOWN[ set to ${_efl_with_binary}])
+
+with_binary_[]m4_defn([DOWN])=${_efl_with_binary}
+
+AC_SUBST(DOWN)
+
+])
diff --git a/m4/efl_doxygen.m4 b/m4/efl_doxygen.m4
new file mode 100644 (file)
index 0000000..dd6bc3e
--- /dev/null
@@ -0,0 +1,99 @@
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if doxygen is available or not.
+
+dnl EFL_CHECK_DOXYGEN([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Test for the doxygen program
+dnl Defines efl_doxygen
+dnl Defines the automake conditionnal EFL_BUILD_DOC
+dnl
+AC_DEFUN([EFL_CHECK_DOXYGEN],
+[
+
+dnl
+dnl Disable the build of the documentation
+dnl
+AC_ARG_ENABLE([doc],
+   [AC_HELP_STRING(
+       [--disable-doc],
+       [Disable documentation build @<:@default=enabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       efl_enable_doc="yes"
+    else
+       efl_enable_doc="no"
+    fi
+   ],
+   [efl_enable_doc="yes"])
+
+AC_MSG_CHECKING([whether to build documentation])
+AC_MSG_RESULT([${efl_enable_doc}])
+
+if test "x${efl_enable_doc}" = "xyes" ; then
+
+dnl
+dnl Specify the file name, without path
+dnl
+
+   efl_doxygen="doxygen"
+
+   AC_ARG_WITH([doxygen],
+      [AC_HELP_STRING(
+          [--with-doxygen=FILE],
+          [doxygen program to use @<:@default=doxygen@:>@])],
+dnl
+dnl Check the given doxygen program.
+dnl
+      [efl_doxygen=${withval}
+       AC_CHECK_PROG([efl_have_doxygen],
+          [${efl_doxygen}],
+          [yes],
+          [no])
+       if test "x${efl_have_doxygen}" = "xno" ; then
+          echo "WARNING:"
+          echo "The doxygen program you specified:"
+          echo "${efl_doxygen}"
+          echo "was not found.  Please check the path and make sure "
+          echo "the program exists and is executable."
+          AC_MSG_WARN([no doxygen detected. Documentation will not be built])
+       fi
+      ],
+      [AC_CHECK_PROG([efl_have_doxygen],
+          [${efl_doxygen}],
+          [yes],
+          [no])
+       if test "x${efl_have_doxygen}" = "xno" ; then
+          echo "WARNING:"
+          echo "The doxygen program was not found in your execute path."
+          echo "You may have doxygen installed somewhere not covered by your path."
+          echo ""
+          echo "If this is the case make sure you have the packages installed, AND"
+          echo "that the doxygen program is in your execute path (see your"
+          echo "shell manual page on setting the \$PATH environment variable), OR"
+          echo "alternatively, specify the program to use with --with-doxygen."
+          AC_MSG_WARN([no doxygen detected. Documentation will not be built])
+       fi
+      ])
+fi
+
+dnl
+dnl Substitution
+dnl
+AC_SUBST([efl_doxygen])
+
+if ! test "x${efl_have_doxygen}" = "xyes" ; then
+   efl_enable_doc="no"
+fi
+
+AM_CONDITIONAL(EFL_BUILD_DOC, test "x${efl_enable_doc}" = "xyes")
+
+if test "x${efl_enable_doc}" = "xyes" ; then
+  m4_default([$1], [:])
+else
+  m4_default([$2], [:])
+fi
+
+])
+
+dnl End of doxygen.m4
diff --git a/m4/efl_threads.m4 b/m4/efl_threads.m4
new file mode 100644 (file)
index 0000000..33d15a3
--- /dev/null
@@ -0,0 +1,206 @@
+dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
+dnl rwlock code added by Mike Blumenkrantz <mike at zentific dot com>
+dnl This code is public domain and can be freely used or copied.
+
+dnl Macro that check if POSIX or Win32 threads library is available or not.
+
+dnl Usage: EFL_CHECK_THREADS(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND])
+dnl Call AC_SUBST(EFL_PTHREAD_CFLAGS)
+dnl Call AC_SUBST(EFL_PTHREAD_LIBS)
+dnl Defines EFL_HAVE_POSIX_THREADS or EFL_HAVE_WIN32_THREADS, and EFL_HAVE_THREADS
+
+AC_DEFUN([EFL_CHECK_THREADS],
+[
+
+dnl configure option
+
+AC_ARG_ENABLE([posix-threads],
+   [AC_HELP_STRING([--disable-posix-threads], [enable POSIX threads code @<:@default=auto@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _efl_enable_posix_threads="yes"
+    else
+       _efl_enable_posix_threads="no"
+    fi
+   ],
+   [_efl_enable_posix_threads="auto"])
+
+AC_MSG_CHECKING([whether to build POSIX threads code])
+AC_MSG_RESULT([${_efl_enable_posix_threads}])
+
+AC_ARG_ENABLE([win32-threads],
+   [AC_HELP_STRING([--disable-win32-threads], [enable Win32 threads code @<:@default=no@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _efl_enable_win32_threads="yes"
+    else
+       _efl_enable_win32_threads="no"
+    fi
+   ],
+   [_efl_enable_win32_threads="no"])
+
+AC_MSG_CHECKING([whether to build Windows threads code])
+AC_MSG_RESULT([${_efl_enable_win32_threads}])
+
+dnl
+dnl * no  + no
+dnl * yes + no  : win32: error,    other : pthread
+dnl * yes + yes : win32 : wthread, other : pthread
+dnl * no  + yes : win32 : wthread, other : error
+
+if  test "x${_efl_enable_posix_threads}" = "xyes" && test "x${_efl_enable_win32_threads}" = "xyes" ; then
+   case "$host_os" in
+      mingw*)
+         _efl_enable_posix_threads=no
+         ;;
+      *)
+         _efl_enable_win32_threads=no
+         ;;
+   esac
+fi
+
+if  test "x${_efl_enable_win32_threads}" = "xyes" ; then
+   case "$host_os" in
+      mingw*)
+         ;;
+      *)
+         AC_MSG_ERROR([Win32 threads support requested but non Windows system found.])
+         ;;
+   esac
+fi
+
+if  test "x${_efl_enable_posix_threads}" = "xyes" ; then
+   case "$host_os" in
+      mingw*)
+         AC_MSG_ERROR([POSIX threads support requested but Windows system found.])
+         ;;
+      *)
+         ;;
+   esac
+fi
+
+dnl check if the compiler supports POSIX threads
+
+case "$host_os" in
+   mingw*)
+      ;;
+   solaris*)
+      _efl_threads_cflags="-mt"
+      _efl_threads_libs="-mt"
+      ;;
+   *)
+      _efl_threads_cflags="-pthread"
+      _efl_threads_libs="-pthread"
+      ;;
+esac
+
+_efl_have_posix_threads="no"
+_efl_have_win32_threads="no"
+
+if test "x${_efl_enable_posix_threads}" = "xyes" || test "x${_efl_enable_posix_threads}" = "xauto" ; then
+
+   SAVE_CFLAGS=${CFLAGS}
+   CFLAGS="${CFLAGS} ${_efl_threads_cflags}"
+   SAVE_LIBS=${LIBS}
+   LIBS="${LIBS} ${_efl_threads_libs}"
+   AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM([[
+#include <pthread.h>
+                       ]],
+                       [[
+pthread_t id;
+id = pthread_self();
+                       ]])],
+      [_efl_have_posix_threads="yes"],
+      [_efl_have_posix_threads="no"])
+   CFLAGS=${SAVE_CFLAGS}
+   LIBS=${SAVE_LIBS}
+
+fi
+
+AC_MSG_CHECKING([whether system support POSIX threads])
+AC_MSG_RESULT([${_efl_have_posix_threads}])
+if test "$x{_efl_enable_posix_threads}" = "xyes" && test "x${_efl_have_posix_threads}" = "xno"; then
+   AC_MSG_ERROR([POSIX threads support requested but not found.])
+fi
+
+EFL_PTHREAD_CFLAGS=""
+EFL_PTHREAD_LIBS=""
+if test "x${_efl_have_posix_threads}" = "xyes" ; then
+   EFL_PTHREAD_CFLAGS=${_efl_threads_cflags}
+   EFL_PTHREAD_LIBS=${_efl_threads_libs}
+fi
+
+AC_SUBST(EFL_PTHREAD_CFLAGS)
+AC_SUBST(EFL_PTHREAD_LIBS)
+
+_efl_enable_debug_threads="no"
+AC_ARG_ENABLE([debug-threads],
+   [AC_HELP_STRING([--enable-debug-threads], [disable assert when you forgot to call eina_threads_init])],
+   [_efl_enable_debug_threads="${enableval}"])
+
+have_debug_threads="no"
+if test "x${_efl_have_posix_threads}" = "xyes" -a "x${_efl_enable_debug_threads}" = "xyes"; then
+   have_debug_threads="yes"
+   AC_DEFINE([EFL_DEBUG_THREADS], [1], [Assert when forgot to call eina_threads_init])
+fi
+
+if test "x${_efl_have_posix_threads}" = "xyes" ; then
+   AC_DEFINE([EFL_HAVE_POSIX_THREADS], [1], [Define to mention that POSIX threads are supported])
+fi
+
+if test "x${_efl_enable_win32_threads}" = "xyes" ; then
+   _efl_have_win32_threads="yes"
+   AC_DEFINE([EFL_HAVE_WIN32_THREADS], [1], [Define to mention that Win32 threads are supported])
+fi
+
+if test "x${_efl_have_posix_threads}" = "xyes" || test "x${_efl_have_win32_threads}" = "xyes" ; then
+   AC_DEFINE([EFL_HAVE_THREADS], [1], [Define to mention that POSIX or Win32 threads are supported])
+fi
+
+AS_IF([test "x$_efl_have_posix_threads" = "xyes" || test "x$_efl_have_win32_threads" = "xyes"], [$1], [$2])
+])
+
+dnl Usage: EFL_CHECK_SPINLOCK(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND])
+dnl Defines EFL_HAVE_POSIX_THREADS_SPINLOCK
+AC_DEFUN([EFL_CHECK_SPINLOCK],
+[
+
+dnl check if the compiler supports pthreads spinlock
+
+_efl_have_posix_threads_spinlock="no"
+
+if test "x${_efl_have_posix_threads}" = "xyes" ; then
+
+   SAVE_CFLAGS=${CFLAGS}
+   CFLAGS="${CFLAGS} ${EFL_PTHREAD_CFLAGS}"
+   SAVE_LIBS=${LIBS}
+   LIBS="${LIBS} ${EFL_PTHREAD_LIBS}"
+   AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM([[
+#include <pthread.h>
+                       ]],
+                       [[
+pthread_spinlock_t lock;
+int res;
+res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
+                       ]])],
+      [_efl_have_posix_threads_spinlock="yes"],
+      [_efl_have_posix_threads_spinlock="no"])
+   CFLAGS=${SAVE_CFLAGS}
+   LIBS=${SAVE_LIBS}
+
+fi
+
+AC_MSG_CHECKING([whether to build POSIX threads spinlock code])
+AC_MSG_RESULT([${_efl_have_posix_threads_spinlock}])
+if test "x${_efl_enable_posix_threads}" = "xyes" && test "x${_efl_have_posix_threads_spinlock}" = "xno" ; then
+   AC_MSG_WARN([POSIX threads support requested but spinlocks are not supported])
+fi
+
+if test "x${_efl_have_posix_threads_spinlock}" = "xyes" ; then
+   AC_DEFINE([EFL_HAVE_POSIX_THREADS_SPINLOCK], [1], [Define to mention that POSIX threads spinlocks are supported])
+fi
+AS_IF([test "x$_efl_have_posix_threads_spinlock" = "xyes"], [$1], [$2])
+])
+
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..be7ccd9
--- /dev/null
@@ -0,0 +1,4 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = lib bin modules edje_externals
diff --git a/src/bin/.cvsignore b/src/bin/.cvsignore
new file mode 100644 (file)
index 0000000..a25cf77
--- /dev/null
@@ -0,0 +1,7 @@
+.deps
+.libs
+Makefile
+Makefile.in
+rage
+raged
+rage_thumb
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
new file mode 100644 (file)
index 0000000..e01dc3c
--- /dev/null
@@ -0,0 +1,133 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/lib \
+-I$(top_builddir)/src/lib \
+-I$(top_srcdir)/src/bin \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+@ELEMENTARY_CFLAGS@ \
+@ELEMENTARY_X_CFLAGS@ \
+@ELEMENTARY_FB_CFLAGS@ \
+@ELEMENTARY_WIN32_CFLAGS@ \
+@ELEMENTARY_WINCE_CFLAGS@ \
+@ELEMENTARY_EDBUS_CFLAGS@ \
+@ELEMENTARY_EFREET_CFLAGS@ \
+@ELEMENTARY_EWEATHER_CFLAGS@ \
+@ELEMENTARY_ETHUMB_CFLAGS@
+
+if ELEMENTARY_WINDOWS_BUILD
+AM_CPPFLAGS += -DELEMENTARY_BUILD
+endif
+
+bin_PROGRAMS = @ELEMENTARY_TEST_PRG@ @ELEMENTARY_CONFIG_PRG@
+if BUILD_QUICKLAUNCH
+bin_PROGRAMS += elementary_quicklaunch elementary_run elementary_testql
+endif
+
+EXTRA_PROGRAMS = elementary_test elementary_config
+
+elementary_test_SOURCES = \
+test.c \
+test_bg.c \
+test_icon.c \
+test_box.c \
+test_button.c \
+test_transit.c \
+test_fileselector_button.c \
+test_fileselector_entry.c \
+test_toggle.c \
+test_table.c \
+test_gengrid.c \
+test_clock.c \
+test_layout.c \
+test_hover.c \
+test_entry.c \
+test_anchorview.c \
+test_anchorblock.c \
+test_toolbar.c \
+test_hoversel.c \
+test_list.c \
+test_inwin.c \
+test_scaling.c \
+test_slider.c \
+test_actionslider.c \
+test_genlist.c \
+test_check.c \
+test_pager.c \
+test_radio.c \
+test_win_state.c \
+test_progressbar.c \
+test_fileselector.c \
+test_separator.c \
+test_scroller.c \
+test_spinner.c \
+test_index.c \
+test_photocam.c \
+test_photo.c \
+test_thumb.c \
+test_icon_desktops.c \
+test_notify.c \
+test_slideshow.c \
+test_menu.c \
+test_panel.c \
+test_panes.c \
+test_map.c \
+test_weather.c \
+test_flip.c \
+test_label.c \
+test_conform.c \
+test_multi.c \
+test_floating.c \
+test_launcher.c \
+test_anim.c \
+test_calendar.c \
+test_tooltip.c \
+test_cursor.c \
+test_focus.c \
+test_focus2.c \
+test_flipselector.c \
+test_diskselector.c \
+test_colorselector.c \
+test_ctxpopup.c \
+test_bubble.c \
+test_store.c
+
+elementary_test_LDADD = $(top_builddir)/src/lib/libelementary.la @ELEMENTARY_EWEATHER_LIBS@ @my_libs@
+elementary_test_LDFLAGS =
+
+elementary_config_SOURCES = \
+config.c
+
+elementary_config_LDADD = $(top_builddir)/src/lib/libelementary.la @ELEMENTARY_EWEATHER_LIBS@
+elementary_config_LDFLAGS =
+
+if BUILD_QUICKLAUNCH
+elementary_quicklaunch_SOURCES = quicklaunch.c
+elementary_quicklaunch_LDADD = $(top_builddir)/src/lib/libelementary.la @ELEMENTARY_EWEATHER_LIBS@
+elementary_quicklaunch_LDFLAGS =
+
+if BUILD_RUN
+elementary_run_SOURCES = run.c
+elementary_run_LDADD =
+elementary_run_LDFLAGS =
+endif
+
+## This is how to build a quicklanch capable app
+# build the shared lib version - libtool produces a .a and .la file as well
+# as a .so - these get put in libdir ($PREIFX/lib) as elementary_testql.so
+# etc. - this is where elementary will expect to find the .so's for
+# quicklaunch apps.
+elementary_testqldir = $(libdir)
+elementary_testql_LTLIBRARIES = elementary_testql.la
+elementary_testql_la_SOURCES = $(elementary_test_SOURCES)
+elementary_testql_la_LIBADD = $(top_builddir)/src/lib/libelementary.la
+elementary_testql_la_CFLAGS =
+elementary_testql_la_LDFLAGS = -module -avoid-version -no-undefined
+elementary_testql_SOURCES = $(elementary_test_SOURCES)
+elementary_testql_LDADD = $(top_builddir)/src/lib/libelementary.la
+elementary_testql_CFLAGS = -DELM_LIB_QUICKLAUNCH=1
+elementary_testql_LDFLAGS =
+endif
diff --git a/src/bin/config.c b/src/bin/config.c
new file mode 100644 (file)
index 0000000..8bc8ed4
--- /dev/null
@@ -0,0 +1,3019 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct _Theme               Theme;
+typedef struct _Fonts_Data          Fonts_Data;
+typedef struct _Elm_Text_Class_Data Elm_Text_Class_Data;
+typedef struct _Elm_Font_Size_Data  Elm_Font_Size_Data;
+
+struct _Theme
+{
+   const char *label;
+   const char *name;
+   const char *path;
+   Eina_Bool   in_search_path;
+};
+
+static Theme *tsel = NULL;
+static Eina_List *themes = NULL;
+
+struct _Elm_Text_Class_Data
+{
+   const char    *name;
+   const char    *desc;
+   const char    *font;
+   const char    *style;
+   Evas_Font_Size size;
+};
+
+struct _Elm_Font_Size_Data
+{
+   const char    *size_str;
+   Evas_Font_Size size;
+};
+
+struct _Fonts_Data
+{
+   Eina_List  *text_classes;
+
+   Eina_Hash  *font_hash;
+   Eina_List  *font_px_list;
+   Eina_List  *font_scale_list;
+
+   const char *cur_font;
+   const char *cur_style;
+   double      cur_size;
+};
+
+#define ELM_LIST_DISABLE(list)                         \
+  do                                                   \
+    {                                                  \
+       const Eina_List *l = elm_list_items_get(list);  \
+       if (l)                                          \
+         {                                             \
+            elm_list_item_show(eina_list_data_get(l)); \
+            elm_object_disabled_set(list, EINA_TRUE);  \
+         }                                             \
+    }                                                  \
+  while (0)
+
+#define ELM_LIST_ENABLE(list)                     \
+  do                                              \
+    {                                             \
+       elm_object_disabled_set(list, EINA_FALSE); \
+    }                                             \
+  while (0)
+
+#define LABEL_FRAME_ADD(label)                                      \
+  do                                                                \
+    {                                                               \
+       pd = elm_frame_add(win);                                     \
+       evas_object_size_hint_weight_set(pd, EVAS_HINT_EXPAND, 0.0); \
+       evas_object_size_hint_align_set(pd, EVAS_HINT_FILL, 0.5);    \
+       elm_object_style_set(pd, "pad_medium");                      \
+       elm_box_pack_end(bx, pd);                                    \
+       evas_object_show(pd);                                        \
+                                                                    \
+       lb = elm_label_add(win);                                     \
+       evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.0); \
+       evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, 0.5);    \
+       elm_label_label_set(lb, label);                              \
+       elm_frame_content_set(pd, lb);                               \
+       evas_object_show(lb);                                        \
+    }                                                               \
+  while (0)
+
+static int quiet = 0;
+static int interactive = 1;
+
+static const char *theme_set = NULL;
+static const char *finger_size_set = NULL;
+static const char *scale_set = NULL;
+static Fonts_Data fdata = {NULL, NULL, NULL, NULL, NULL, NULL, 0.0};
+
+static void
+_font_styles_list_sel(void *data   __UNUSED__,
+                      Evas_Object *obj,
+                      void        *event_info);
+
+static void
+config_exit(void *data       __UNUSED__,
+            Evas_Object *obj __UNUSED__,
+            void *event_info __UNUSED__)
+{
+   Elm_Text_Class_Data *tc_data;
+   Elm_Font_Size_Data *sd;
+
+   EINA_LIST_FREE(fdata.text_classes, tc_data)
+     {
+        eina_stringshare_del(tc_data->name);
+        eina_stringshare_del(tc_data->desc);
+        eina_stringshare_del(tc_data->font);
+        eina_stringshare_del(tc_data->style);
+        free(tc_data);
+     }
+
+   elm_font_available_hash_del(fdata.font_hash);
+
+   EINA_LIST_FREE(fdata.font_px_list, sd)
+     {
+        eina_stringshare_del(sd->size_str);
+        free(sd);
+     }
+
+   EINA_LIST_FREE(fdata.font_scale_list, sd)
+     {
+        eina_stringshare_del(sd->size_str);
+        free(sd);
+     }
+
+   if (fdata.cur_font) eina_stringshare_del(fdata.cur_font);
+   if (fdata.cur_style) eina_stringshare_del(fdata.cur_style);
+
+   elm_config_save();
+   elm_exit(); /* exit the program's main loop that runs in elm_run() */
+}
+
+static void
+sb_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   Eina_Bool val = elm_check_state_get(obj);
+   Eina_Bool sb = elm_scroll_bounce_enabled_get();
+
+   if (val == sb) return;
+   elm_scroll_bounce_enabled_all_set(val);
+
+   /*TODO: enable/disable subordinate sliders (make 'em support it 1st)*/
+}
+
+static void
+bf_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+bf_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double bf = elm_scroll_bounce_friction_get();
+   double val = elm_slider_value_get(obj);
+
+   if (bf == val) return;
+   elm_scroll_bounce_friction_all_set(val);
+}
+
+static void
+ps_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+ps_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double ps = elm_scroll_page_scroll_friction_get();
+   double val = elm_slider_value_get(obj);
+
+   if (ps == val) return;
+   elm_scroll_page_scroll_friction_all_set(val);
+}
+
+static void
+bis_round(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+bis_change(void *data       __UNUSED__,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   double bis = elm_scroll_bring_in_scroll_friction_get();
+   double val = elm_slider_value_get(obj);
+
+   if (bis == val) return;
+   elm_scroll_bring_in_scroll_friction_all_set(val);
+}
+
+static void
+zf_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+zf_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double zf = elm_scroll_zoom_friction_get();
+   double val = elm_slider_value_get(obj);
+
+   if (zf == val) return;
+   elm_scroll_zoom_friction_all_set(val);
+}
+
+static void
+ts_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   Eina_Bool val = elm_check_state_get(obj);
+   Eina_Bool sb = elm_scroll_bounce_enabled_get();
+
+   if (val == sb) return;
+   elm_scroll_thumbscroll_enabled_all_set(val);
+
+   /*TODO: enable/disable subordinate sliders (make 'em support it 1st)*/
+}
+
+static void
+tst_round(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+tst_change(void *data       __UNUSED__,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   double tst = elm_scroll_thumbscroll_threshold_get();
+   double val = elm_slider_value_get(obj);
+
+   if (tst == val) return;
+   elm_scroll_thumbscroll_threshold_all_set(val);
+}
+
+static void
+tsmt_round(void *data       __UNUSED__,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+tsmt_change(void *data       __UNUSED__,
+            Evas_Object     *obj,
+            void *event_info __UNUSED__)
+{
+   double tsmt = elm_scroll_thumbscroll_momentum_threshold_get();
+   double val = elm_slider_value_get(obj);
+
+   if (tsmt == val) return;
+   elm_scroll_thumbscroll_momentum_threshold_all_set(val);
+}
+
+static void
+tsf_round(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+tsf_change(void *data       __UNUSED__,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   double tsf = elm_scroll_thumbscroll_friction_get();
+   double val = elm_slider_value_get(obj);
+
+   if (tsf == val) return;
+   elm_scroll_thumbscroll_friction_all_set(val);
+}
+
+static void
+tsbf_round(void *data       __UNUSED__,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+tsbf_change(void *data       __UNUSED__,
+            Evas_Object     *obj,
+            void *event_info __UNUSED__)
+{
+   double tsbf = elm_scroll_thumbscroll_border_friction_get();
+   double val = elm_slider_value_get(obj);
+
+   if (tsbf == val) return;
+   elm_scroll_thumbscroll_border_friction_all_set(val);
+}
+
+static void
+cf_enable(void *data,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   Eina_Bool cf = elm_cache_flush_enmabled_get();
+   Eina_Bool val = elm_check_state_get(obj); 
+
+   if (cf == val) return;
+   elm_object_disabled_set((Evas_Object *)data, !val);
+   elm_cache_flush_enabled_all_set(val);
+}
+
+static void
+cf_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 5.0))) / 5.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+cf_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double cf = elm_cache_flush_interval_get();
+   double val = elm_slider_value_get(obj);
+
+   if (cf == val) return;
+   elm_cache_flush_interval_all_set(val);
+}
+
+static void
+fc_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+fc_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double font_cache = elm_font_cache_get();
+   double val = elm_slider_value_get(obj);
+
+   if (font_cache == val) return;
+   elm_font_cache_all_set(val * 1024);
+}
+
+static void
+ic_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+ic_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double image_cache = elm_image_cache_get();
+   double val = elm_slider_value_get(obj);
+
+   if (image_cache == val) return;
+   elm_image_cache_all_set(val * 1024);
+}
+
+static void
+sc_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 10.0))) / 10.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+sc_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double scale = elm_scale_get();
+   double val = elm_slider_value_get(obj);
+
+   if (scale == val) return;
+   elm_scale_all_set(val);
+}
+
+static void
+fs_round(void *data       __UNUSED__,
+         Evas_Object     *obj,
+         void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 5.0))) / 5.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+fs_change(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double fs = elm_finger_size_get();
+   double val = elm_slider_value_get(obj);
+
+   if (fs == val) return;
+   elm_finger_size_all_set(val);
+}
+
+static void
+efc_round(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 5.0))) / 5.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+efc_change(void *data       __UNUSED__,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   double efc = elm_edje_file_cache_get();
+   double val = elm_slider_value_get(obj);
+
+   if (efc == val) return;
+   elm_edje_file_cache_all_set(val);
+}
+
+static void
+ecc_round(void *data       __UNUSED__,
+          Evas_Object     *obj,
+          void *event_info __UNUSED__)
+{
+   double val = elm_slider_value_get(obj);
+   double v;
+
+   v = ((double)((int)(val * 5.0))) / 5.0;
+   if (v != val) elm_slider_value_set(obj, v);
+}
+
+static void
+ecc_change(void *data       __UNUSED__,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   double ecc = elm_edje_collection_cache_get();
+   double val = elm_slider_value_get(obj);
+
+   if (ecc == val) return;
+   elm_edje_collection_cache_all_set(val);
+}
+
+static void
+_status_basic(Evas_Object *win,
+              Evas_Object *bx0)
+{
+   Evas_Object *lb, *fr;
+
+   fr = elm_frame_add(win);
+   evas_object_size_hint_weight_set(fr, 1.0, 1.0);
+   elm_frame_label_set(fr, "Information");
+   elm_box_pack_end(bx0, fr);
+   evas_object_show(fr);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                       "Applying configuration change"
+                       );
+   elm_frame_content_set(fr, lb);
+   evas_object_show(lb);
+}
+
+static void
+_status_config(Evas_Object *win,
+               Evas_Object *bx0)
+{
+   Evas_Object *lb, *pd, *bx, *fr, *sl, *sp;
+
+   fr = elm_frame_add(win);
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_label_set(fr, "Sizing");
+   elm_box_pack_end(bx0, fr);
+   evas_object_show(fr);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
+
+   LABEL_FRAME_ADD("<hilight>Scale</>");
+
+   sl = elm_slider_add(win);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.2f");
+   elm_slider_indicator_format_set(sl, "%1.2f");
+   elm_slider_min_max_set(sl, 0.25, 5.0);
+   elm_slider_value_set(sl, elm_scale_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", sc_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", sc_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   LABEL_FRAME_ADD("<hilight>Finger Size</><br>");
+
+   sl = elm_slider_add(win);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 5, 200);
+   elm_slider_value_set(sl, elm_finger_size_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", fs_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", fs_change, NULL);
+
+   // FIXME: add theme selector (basic mode and advanced for fallbacks)
+   // FIXME: save config
+   // FIXME: profile selector / creator etc.
+   elm_frame_content_set(fr, bx);
+   evas_object_show(bx);
+}
+
+static void
+_flip_to(Evas_Object *win,
+         const char  *name)
+{
+   Evas_Object *wid, *pager;
+   wid = evas_object_data_get(win, name);
+   pager = evas_object_data_get(win, "pager");
+   elm_pager_content_promote(pager, wid);
+}
+
+static void
+_cf_sizing(void            *data,
+           Evas_Object *obj __UNUSED__,
+           void *event_info __UNUSED__)
+{
+   _flip_to(data, "sizing");
+}
+
+static void
+_cf_themes(void            *data,
+           Evas_Object *obj __UNUSED__,
+           void *event_info __UNUSED__)
+{
+   _flip_to(data, "themes");
+}
+
+static void
+_cf_fonts(void            *data,
+          Evas_Object *obj __UNUSED__,
+          void *event_info __UNUSED__)
+{
+   _flip_to(data, "fonts");
+}
+
+static void
+_cf_profiles(void            *data,
+             Evas_Object *obj __UNUSED__,
+             void *event_info __UNUSED__)
+{
+   _flip_to(data, "profiles");
+}
+
+static void
+_cf_scrolling(void            *data,
+              Evas_Object *obj __UNUSED__,
+              void *event_info __UNUSED__)
+{
+   _flip_to(data, "scrolling");
+}
+
+static void
+_cf_rendering(void            *data,
+              Evas_Object *obj __UNUSED__,
+              void *event_info __UNUSED__)
+{
+   _flip_to(data, "rendering");
+}
+
+static void
+_cf_caches(void            *data,
+           Evas_Object *obj __UNUSED__,
+           void *event_info __UNUSED__)
+{
+   _flip_to(data, "caches");
+}
+
+const char *
+_elm_theme_current_get(const char *theme_search_order)
+{
+   const char *ret;
+   const char *p;
+
+   if (!theme_search_order)
+     return NULL;
+
+   for (p = theme_search_order;; p++)
+     {
+        if ((*p == ':') || (!*p))
+          {
+             if (p > theme_search_order)
+               {
+                  char *n = malloc(p - theme_search_order + 1);
+                  if (!n)
+                    return NULL;
+
+                  strncpy(n, theme_search_order, p - theme_search_order);
+                  n[p - theme_search_order] = 0;
+                  ret = eina_stringshare_add(n);
+                  free(n);
+                  break;
+               }
+          }
+     }
+
+   return ret;
+}
+
+static void
+_font_overlay_set_all(void            *data,
+                      Evas_Object *obj __UNUSED__,
+                      void *event_info __UNUSED__)
+{
+   Evas_Object *win, *fclasses, *fnames, *fstyles, *fsizes;
+   Elm_Text_Class_Data *tc_data, *tc;
+   Elm_List_Item *it;
+   Eina_List *l;
+
+   win = data;
+
+   fclasses = evas_object_data_get(win, "font_classes_list");
+   it = elm_list_selected_item_get(fclasses);
+   if (!it) return;
+   tc_data = elm_list_item_data_get(it);
+
+   fnames = evas_object_data_get(win, "font_names_list");
+   fstyles = evas_object_data_get(win, "font_styles_list");
+   fsizes = evas_object_data_get(win, "font_sizes_list");
+
+   EINA_LIST_FOREACH(fdata.text_classes, l, tc)
+     {
+        eina_stringshare_replace(&tc->font, tc_data->font);
+        eina_stringshare_replace(&tc->style, tc_data->style);
+        tc->size = tc_data->size;
+     }
+
+   elm_config_save();
+}
+
+static void
+_font_overlay_reset(void            *data,
+                    Evas_Object *obj __UNUSED__,
+                    void *event_info __UNUSED__)
+{
+   Evas_Object *win, *fclasses, *fnames, *fstyles, *fsizes;
+   Elm_Text_Class_Data *tc_data;
+   Elm_List_Item *it;
+
+   win = data;
+
+   fclasses = evas_object_data_get(win, "font_classes_list");
+   it = elm_list_selected_item_get(fclasses);
+   if (!it) return;
+   tc_data = elm_list_item_data_get(it);
+
+   fnames = evas_object_data_get(win, "font_names_list");
+   fstyles = evas_object_data_get(win, "font_styles_list");
+   fsizes = evas_object_data_get(win, "font_sizes_list");
+
+   elm_font_overlay_unset(tc_data->name);
+
+   eina_stringshare_replace(&fdata.cur_font, NULL);
+   eina_stringshare_replace(&tc_data->font, NULL);
+   eina_stringshare_replace(&fdata.cur_style, NULL);
+   eina_stringshare_replace(&tc_data->style, NULL);
+   fdata.cur_size = 0.0;
+   tc_data->size = 0.0;
+
+   ELM_LIST_DISABLE(fnames);
+   ELM_LIST_DISABLE(fstyles);
+   ELM_LIST_DISABLE(fsizes);
+
+   elm_config_save();
+}
+
+static void
+_font_overlay_reset_all(void            *data,
+                        Evas_Object *obj __UNUSED__,
+                        void *event_info __UNUSED__)
+{
+   Evas_Object *win, *fclasses, *fnames, *fstyles, *fsizes;
+   Elm_Text_Class_Data *tc_data;
+   Elm_List_Item *it;
+   Eina_List *l;
+
+   win = data;
+   eina_stringshare_replace(&fdata.cur_font, NULL);
+   eina_stringshare_replace(&fdata.cur_style, NULL);
+   fdata.cur_size = 0.0;
+
+   EINA_LIST_FOREACH(fdata.text_classes, l, tc_data)
+     {
+        elm_font_overlay_unset(tc_data->name);
+
+        eina_stringshare_replace(&tc_data->font, NULL);
+        eina_stringshare_replace(&tc_data->style, NULL);
+        tc_data->size = 0.0;
+     }
+
+   fclasses = evas_object_data_get(win, "font_classes_list");
+   fnames = evas_object_data_get(win, "font_names_list");
+   fstyles = evas_object_data_get(win, "font_styles_list");
+   fsizes = evas_object_data_get(win, "font_sizes_list");
+
+   it = elm_list_selected_item_get(fclasses);
+   if (it) elm_list_item_selected_set(it, EINA_FALSE);
+
+   ELM_LIST_DISABLE(fnames);
+   ELM_LIST_DISABLE(fstyles);
+   ELM_LIST_DISABLE(fsizes);
+
+   elm_config_save();
+}
+
+static void
+_font_overlay_change(void *data       __UNUSED__,
+                     Evas_Object *obj __UNUSED__,
+                     void *event_info __UNUSED__)
+{
+   Elm_Text_Class_Data *tc_data;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(fdata.text_classes, l, tc_data)
+     {
+        if (tc_data->font)
+          {
+             const char *name;
+
+             name = elm_font_fontconfig_name_get(tc_data->font,
+                                                 tc_data->style);
+             elm_font_overlay_set(tc_data->name, name,
+                                  tc_data->size ? tc_data->size : -100);
+             elm_font_fontconfig_name_free(name);
+          }
+        else
+          elm_font_overlay_unset(tc_data->name);
+     }
+
+   elm_config_save();
+   elm_font_overlay_all_apply();
+
+   /* TODO: apply hinting */
+}
+
+static void
+_profile_change_do(Evas_Object *win,
+                   const char  *profile)
+{
+   int flush_interval, font_c, image_c, edje_file_c, edje_col_c, ts_threshould;
+   double scale, s_bounce_friction, ts_momentum_threshold, ts_friction,
+          ts_border_friction, page_friction, bring_in_friction, zoom_friction;
+   const char *curr_theme, *curr_engine;
+   const Eina_List *l_items, *l;
+   Eina_Bool s_bounce, ts;
+   Elm_List_Item *it;
+   Elm_Theme *th;
+   int fs;
+
+   elm_profile_all_set(profile);
+
+   scale = elm_scale_get();
+   fs = elm_finger_size_get();
+   flush_interval = elm_cache_flush_interval_get();
+   font_c = elm_font_cache_get();
+   image_c = elm_image_cache_get();
+   edje_file_c = elm_edje_file_cache_get();
+   edje_col_c = elm_edje_collection_cache_get();
+
+   s_bounce = elm_scroll_bounce_enabled_get();
+   s_bounce_friction = elm_scroll_bounce_friction_get();
+   ts = elm_scroll_thumbscroll_enabled_get();
+   ts_threshould = elm_scroll_thumbscroll_threshold_get();
+   ts_momentum_threshold = elm_scroll_thumbscroll_momentum_threshold_get();
+   ts_friction = elm_scroll_thumbscroll_friction_get();
+   ts_border_friction = elm_scroll_thumbscroll_border_friction_get();
+   page_friction = elm_scroll_page_scroll_friction_get();
+   bring_in_friction = elm_scroll_bring_in_scroll_friction_get();
+   zoom_friction = elm_scroll_zoom_friction_get();
+
+   /* gotta update root windows' atoms */
+   elm_scale_all_set(scale);
+   elm_slider_value_set(evas_object_data_get(win, "scale_slider"), scale);
+   elm_finger_size_all_set(fs);
+   elm_slider_value_set(evas_object_data_get(win, "fs_slider"), fs);
+
+   elm_cache_flush_interval_all_set(flush_interval);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "cache_flush_interval_slider"),
+                        flush_interval);
+   elm_font_cache_all_set(font_c);
+   elm_slider_value_set(evas_object_data_get(win, "font_cache_slider"),
+                        font_c / 1024.0);
+   elm_image_cache_all_set(image_c);
+   elm_slider_value_set(evas_object_data_get(win, "image_cache_slider"),
+                        image_c / 1024.0);
+   elm_edje_file_cache_all_set(edje_file_c);
+   elm_slider_value_set(evas_object_data_get(win, "edje_file_cache_slider"),
+                        edje_file_c);
+   elm_edje_collection_cache_all_set(edje_col_c);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "edje_collection_cache_slider"),
+                        edje_col_c);
+
+   elm_scroll_bounce_enabled_all_set(s_bounce);
+   elm_check_state_set(evas_object_data_get(win, "scroll_bounce_check"),
+                       s_bounce);
+   elm_scroll_bounce_friction_all_set(s_bounce_friction);
+   elm_slider_value_set(evas_object_data_get(win, "bounce_friction_slider"),
+                        s_bounce_friction);
+   elm_scroll_thumbscroll_enabled_all_set(ts);
+   elm_check_state_set(evas_object_data_get(win, "thumbscroll_check"), ts);
+   elm_scroll_thumbscroll_threshold_all_set(ts_threshould);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "thumbscroll_threshold_slider"),
+                        ts_threshould);
+   elm_scroll_thumbscroll_momentum_threshold_all_set(ts_momentum_threshold);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "ts_momentum_threshold_slider"),
+                        ts_momentum_threshold);
+   elm_scroll_thumbscroll_friction_all_set(ts_friction);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "thumbscroll_friction_slider"),
+                        ts_friction);
+   elm_scroll_thumbscroll_border_friction_all_set(ts_border_friction);
+   elm_slider_value_set(evas_object_data_get(win, "ts_border_friction_slider"),
+                        ts_border_friction);
+   elm_scroll_page_scroll_friction_all_set(page_friction);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "page_scroll_friction_slider"),
+                        page_friction);
+   elm_scroll_bring_in_scroll_friction_all_set(bring_in_friction);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "bring_in_scroll_friction_slider"),
+                        bring_in_friction);
+   elm_scroll_zoom_friction_all_set(zoom_friction);
+   elm_slider_value_set(evas_object_data_get(win,
+                                             "zoom_scroll_friction_slider"),
+                        zoom_friction);
+
+   curr_theme = _elm_theme_current_get(elm_theme_get(NULL));
+   elm_theme_all_set(curr_theme);
+
+   th = elm_theme_new();
+   elm_theme_set(th, curr_theme);
+   elm_object_theme_set(evas_object_data_get(win, "theme_preview"), th);
+   elm_theme_free(th);
+   eina_stringshare_del(curr_theme);
+
+   curr_engine = elm_engine_current_get();
+   l_items = elm_list_items_get(evas_object_data_get(win, "engines_list"));
+   EINA_LIST_FOREACH(l_items, l, it)
+     {
+        if (!strcmp(elm_list_item_data_get(it), curr_engine))
+          {
+             elm_list_item_selected_set(it, EINA_TRUE);
+             break;
+          }
+     }
+}
+
+static void
+_engine_use(void            *data,
+            Evas_Object *obj __UNUSED__,
+            void *event_info __UNUSED__)
+{
+   Evas_Object *li;
+   const char *selection;
+
+   li = data;
+   selection = elm_list_item_data_get(elm_list_selected_item_get(li));
+
+   if (!strcmp(elm_engine_current_get(), selection))
+     return;
+
+   elm_engine_set(selection);
+   elm_config_save(); /* make sure new engine has its data dir */
+}
+
+static void
+_profile_use(void            *data,
+             Evas_Object *obj __UNUSED__,
+             void *event_info __UNUSED__)
+{
+   Evas_Object *li;
+   const char *selection;
+   const char *profile;
+
+   li = data;
+   selection = elm_list_item_data_get(elm_list_selected_item_get(li));
+   profile = elm_profile_current_get();
+
+   if (!profile)
+     {
+        fprintf(stderr, "No profile currently set!\n"); /* FIXME: log domain */
+        return;
+     }
+
+   if (!strcmp(profile, selection))
+     return;
+
+   elm_config_save(); /* dump config into old profile's data dir */
+   elm_profile_set(selection); /* just here to update info for getters below */
+
+   _profile_change_do(elm_object_top_widget_get(li), selection);
+   elm_config_save(); /* make sure new profile has its data dir */
+}
+
+static void
+_btn_todo(void *data       __UNUSED__,
+          Evas_Object *obj __UNUSED__,
+          void *event_info __UNUSED__)
+{
+   printf("To be done!\n");
+}
+
+static void
+_profile_reset(void            *data,
+               Evas_Object *obj __UNUSED__,
+               void *event_info __UNUSED__)
+{
+   const char *selection, *curr;
+   const char *pdir;
+   Evas_Object *li;
+
+   li = data;
+   selection = elm_list_item_data_get(elm_list_selected_item_get(li));
+   curr = elm_profile_current_get();
+
+   elm_config_save(); /* dump config into old profile's data dir */
+
+   pdir = elm_profile_dir_get(selection, EINA_TRUE);
+   if (!pdir)
+     return;
+
+   ecore_file_recursive_rm(pdir);
+   elm_profile_dir_free(pdir);
+
+   elm_config_reload();
+
+   _profile_change_do(elm_object_top_widget_get(li), curr);
+   elm_config_save(); /* make sure new profile has its data dir */
+}
+
+static void
+_theme_use(void *data       __UNUSED__,
+           Evas_Object *obj __UNUSED__,
+           void *event_info __UNUSED__)
+{
+   const char *defth;
+   char *newth;
+   Theme *t = tsel;
+
+   if (!t) return;
+   defth = elm_theme_get(NULL);
+   newth = malloc(strlen(defth) + 1 + strlen(t->name) + 1);
+   if (newth)
+     {
+        char *rest;
+
+        newth[0] = 0;
+        rest = strchr(defth, ':');
+        if (!rest)
+          strcpy(newth, t->name);
+        else
+          {
+             strcpy(newth, t->name);
+             strcat(newth, rest);
+          }
+        elm_theme_all_set(newth);
+        free(newth);
+     }
+}
+
+static void
+_theme_sel(void            *data,
+           Evas_Object     *obj,
+           void *event_info __UNUSED__)
+{
+   Theme *t = data;
+   Evas_Object *win = elm_object_top_widget_get(obj);
+   Evas_Object *sample = evas_object_data_get(win, "theme_preview");
+   Elm_Theme *th;
+   const char *defth;
+   char *newth;
+
+   tsel = t;
+   defth = elm_theme_get(NULL);
+   newth = malloc(strlen(defth) + 1 + strlen(t->name) + 1);
+   th = elm_theme_new();
+   if (newth)
+     {
+        char *rest;
+
+        newth[0] = 0;
+        rest = strchr(defth, ':');
+        if (!rest)
+          strcpy(newth, t->name);
+        else
+          {
+             strcpy(newth, t->name);
+             strcat(newth, rest);
+          }
+        elm_theme_set(th, newth);
+        free(newth);
+     }
+   elm_object_theme_set(sample, th);
+   elm_theme_free(th);
+}
+
+/*static void
+   _theme_browse(void *data, Evas_Object *obj, void *event_info)
+   {
+   printf("not implemented\n");
+   }*/
+
+static void
+_status_config_sizing(Evas_Object *win,
+                      Evas_Object *pager)
+{
+   Evas_Object *lb, *pd, *bx, *sl, *sp;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
+
+   LABEL_FRAME_ADD("<hilight>Scale</>");
+
+   sl = elm_slider_add(win);
+   evas_object_data_set(win, "scale_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.2f");
+   elm_slider_indicator_format_set(sl, "%1.2f");
+   elm_slider_min_max_set(sl, 0.25, 5.0);
+   elm_slider_value_set(sl, elm_scale_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", sc_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", sc_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   LABEL_FRAME_ADD("<hilight>Finger Size</><br>");
+
+   sl = elm_slider_add(win);
+   evas_object_data_set(win, "fs_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 5, 200);
+   elm_slider_value_set(sl, elm_finger_size_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", fs_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", fs_change, NULL);
+
+   evas_object_data_set(win, "sizing", bx);
+
+   elm_pager_content_push(pager, bx);
+}
+
+static Evas_Object *
+_sample_theme_new(Evas_Object *win)
+{
+   Evas_Object *base, *bg, *bt, *ck, *rd, *rdg, *sl, *fr, *li, *rc, *sp;
+
+   base = elm_table_add(win);
+   evas_object_size_hint_weight_set(base, 1.0, 1.0);
+   evas_object_size_hint_align_set(base, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, 1.0, 1.0);
+   evas_object_size_hint_align_set(bg, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(base, bg, 0, 0, 2, 5);
+   evas_object_show(bg);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button");
+   elm_table_pack(base, bt, 0, 0, 1, 1);
+   evas_object_show(bt);
+
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Check");
+   elm_table_pack(base, ck, 0, 1, 1, 1);
+   evas_object_show(ck);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 0);
+   elm_radio_label_set(rd, "Radio 1");
+   elm_table_pack(base, rd, 1, 0, 1, 1);
+   evas_object_show(rd);
+   rdg = rd;
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 1);
+   elm_radio_label_set(rd, "Radio 2");
+   elm_radio_group_add(rd, rdg);
+   elm_table_pack(base, rd, 1, 1, 1, 1);
+   evas_object_show(rd);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, 1.0, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_table_pack(base, sp, 0, 2, 2, 1);
+   evas_object_show(sp);
+
+   sl = elm_slider_add(win);
+   elm_slider_label_set(sl, "Slider");
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_min_max_set(sl, 1, 10);
+   elm_slider_value_set(sl, 4);
+   evas_object_size_hint_weight_set(sl, 1.0, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(base, sl, 0, 3, 2, 1);
+   evas_object_show(sl);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Frame");
+   elm_table_pack(base, fr, 0, 4, 2, 1);
+   evas_object_size_hint_weight_set(fr, 1.0, 1.0);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(fr);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, 1.0, 1.0);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, li);
+   evas_object_show(li);
+
+   elm_list_item_append(li, "List Item 1", NULL, NULL, NULL, NULL);
+   elm_list_item_append(li, "Second Item", NULL, NULL, NULL, NULL);
+   elm_list_item_append(li, "Third Item", NULL, NULL, NULL, NULL);
+   elm_list_go(li);
+
+   rc = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_size_hint_min_set(rc, 160, 120);
+   elm_table_pack(base, rc, 0, 4, 2, 1);
+
+   return base;
+}
+
+static void
+_status_config_themes(Evas_Object *win,
+                      Evas_Object *pager)
+{
+   Evas_Object *tb, *rc, *sc, *sp, *li, *pd, *fr, *bt, *sample;
+   Eina_List *list, *l;
+   char *th, *s, *ext;
+
+   tb = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb, 1.0, 1.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   rc = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_size_hint_min_set(rc, 0, 130);
+   elm_table_pack(tb, rc, 0, 0, 1, 1);
+
+   rc = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_size_hint_min_set(rc, 0, 200);
+   elm_table_pack(tb, rc, 0, 1, 1, 1);
+
+   /////////////////////////////////////////////
+
+   pd = elm_frame_add(win);
+   elm_object_style_set(pd, "pad_medium");
+   evas_object_size_hint_weight_set(pd, 1.0, 1.0);
+   evas_object_size_hint_align_set(pd, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, pd, 0, 0, 1, 1);
+   evas_object_show(pd);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, 1.0, 1.0);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(pd, li);
+   evas_object_show(li);
+
+   list = elm_theme_name_available_list_new();
+   EINA_LIST_FOREACH(list, l, th)
+     {
+        Theme *t;
+
+        t = calloc(1, sizeof(Theme));
+        t->name = eina_stringshare_add(th);
+        s = elm_theme_list_item_path_get(th, &(t->in_search_path));
+        if (s)
+          {
+             t->path = eina_stringshare_add(s);
+             free(s);
+          }
+        if (t->in_search_path)
+          {
+             s = strdup(th);
+             if (s)
+               {
+                  s[0] = toupper(s[0]);
+                  t->label = eina_stringshare_add(s);
+                  free(s);
+               }
+             else
+               t->label = eina_stringshare_add(s);
+          }
+        else
+          {
+             s = strdup(ecore_file_file_get(th));
+             if (s)
+               {
+                  s[0] = toupper(s[0]);
+                  ext = strrchr(s, '.');
+                  if (ext) *ext = 0;
+                  t->label = eina_stringshare_add(s);
+                  free(s);
+               }
+             else
+               t->label = eina_stringshare_add(s);
+          }
+        themes = eina_list_append(themes, t);
+        elm_list_item_append(li, t->label, NULL, NULL, _theme_sel, t);
+     }
+   elm_theme_name_available_list_free(list);
+
+   elm_list_go(li);
+
+   pd = elm_frame_add(win);
+   elm_object_style_set(pd, "pad_medium");
+   evas_object_size_hint_weight_set(pd, 1.0, 1.0);
+   evas_object_size_hint_align_set(pd, 0.9, 0.9);
+   elm_table_pack(tb, pd, 0, 0, 1, 1);
+   evas_object_show(pd);
+
+   /* FIXME: not implemented yet
+      bt = elm_button_add(win);
+      evas_object_smart_callback_add(bt, "clicked", _theme_browse, win);
+      elm_button_label_set(bt, "Browse...");
+      evas_object_size_hint_weight_set(bt, 1.0, 1.0);
+      evas_object_size_hint_align_set(bt, 0.9, 0.9);
+      elm_frame_content_set(pd, bt);
+      evas_object_show(bt);
+    */
+   pd = elm_frame_add(win);
+   elm_object_style_set(pd, "pad_medium");
+   evas_object_size_hint_weight_set(pd, 1.0, 0.0);
+   evas_object_size_hint_align_set(pd, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, pd, 0, 1, 1, 1);
+   evas_object_show(pd);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Preview");
+   evas_object_size_hint_weight_set(fr, 1.0, 1.0);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(pd, fr);
+   evas_object_show(fr);
+
+   sc = elm_scroller_add(win);
+   elm_scroller_bounce_set(sc, 0, 0);
+   evas_object_size_hint_weight_set(sc, 1.0, 1.0);
+   evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, sc);
+   evas_object_show(sc);
+
+   sample = _sample_theme_new(win);
+   elm_scroller_content_set(sc, sample);
+   evas_object_show(sample);
+   evas_object_data_set(win, "theme_preview", sample);
+
+   /////////////////////////////////////////////
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, 1.0, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_table_pack(tb, sp, 0, 2, 1, 1);
+   evas_object_show(sp);
+
+   pd = elm_frame_add(win);
+   elm_object_style_set(pd, "pad_medium");
+   evas_object_size_hint_weight_set(pd, 0.0, 0.0);
+   evas_object_size_hint_align_set(pd, 0.5, 0.5);
+   elm_table_pack(tb, pd, 0, 3, 1, 1);
+   evas_object_show(pd);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _theme_use, win);
+   elm_button_label_set(bt, "Use Theme");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_frame_content_set(pd, bt);
+   evas_object_show(bt);
+
+   evas_object_data_set(win, "themes", tb);
+   elm_pager_content_push(pager, tb);
+}
+
+static void
+_font_preview_update(Evas_Object *win)
+{
+   Evas_Font_Size sz;
+   const char *name;
+
+   if (!fdata.cur_font)
+     return;
+
+   name = elm_font_fontconfig_name_get(fdata.cur_font, fdata.cur_style);
+   sz = fdata.cur_size;
+
+   if (sz < 0)
+     sz = (-sz * 10) / 100;
+   if (sz == 0)
+     sz = 10;
+
+   edje_object_text_class_set(evas_object_data_get(win, "font_preview"),
+                              "font_preview", name, sz);
+
+   elm_font_fontconfig_name_free(name);
+}
+
+static void
+_font_classes_list_sel(void *data   __UNUSED__,
+                       Evas_Object *obj,
+                       void        *event_info)
+{
+   const Eina_List *f_names_items, *l;
+   Elm_Text_Class_Data *tc_data;
+   Evas_Object *f_names_list;
+   Elm_List_Item *it;
+
+   tc_data = elm_list_item_data_get(event_info);
+
+   f_names_list = evas_object_data_get(elm_object_top_widget_get(obj),
+                                       "font_names_list");
+   ELM_LIST_ENABLE(f_names_list);
+
+   f_names_items = elm_list_items_get(f_names_list);
+
+   EINA_LIST_FOREACH(f_names_items, l, it)
+     {
+        const char *l;
+
+        l = elm_list_item_label_get(it);
+
+        if (tc_data->font && !strcmp(l, tc_data->font))
+          {
+             elm_list_item_selected_set(it, EINA_TRUE);
+             elm_list_item_show(it);
+             break;
+          }
+     }
+}
+
+static void
+_font_names_list_sel(void *data   __UNUSED__,
+                     Evas_Object *obj,
+                     void        *event_info)
+{
+   Evas_Object *style_list, *cls_list, *sizes_list, *win;
+   const char *style, *sel_font;
+   Elm_Text_Class_Data *tc_data;
+   Elm_List_Item *it, *fc_it;
+   Elm_Font_Properties *efp;
+   const Eina_List *l;
+
+   it = event_info;
+   sel_font = elm_list_item_label_get(it);
+
+   win = elm_object_top_widget_get(obj);
+   style_list = evas_object_data_get(win, "font_styles_list");
+   cls_list = evas_object_data_get(win, "font_classes_list");
+   sizes_list = evas_object_data_get(win, "font_sizes_list");
+
+   fc_it = elm_list_selected_item_get(cls_list);
+   if (!fc_it) return;  /* should not happen, fonts list disabled in
+                         * this case */
+
+   eina_stringshare_replace(&fdata.cur_font, sel_font);
+
+   tc_data = elm_list_item_data_get(fc_it);
+   if (tc_data->font) eina_stringshare_del(tc_data->font);
+   if (fdata.cur_font) tc_data->font = eina_stringshare_ref(fdata.cur_font);
+
+   /* load styles list */
+   efp = eina_hash_find(fdata.font_hash, sel_font);
+
+   ELM_LIST_ENABLE(style_list);
+   elm_list_clear(style_list);
+
+   evas_event_freeze(evas_object_evas_get(style_list));
+   edje_freeze();
+
+   it = NULL;
+
+   EINA_LIST_FOREACH(efp->styles, l, style)
+     {
+        Elm_List_Item *i;
+
+        i = elm_list_item_append(style_list, style, NULL, NULL,
+                                 _font_styles_list_sel, NULL);
+
+        if (tc_data->style && (!strcmp(style, tc_data->style)))
+          it = i;
+     }
+
+   elm_list_go(style_list);
+
+   edje_thaw();
+   evas_event_thaw(evas_object_evas_get(style_list));
+
+   if (it)
+     elm_list_item_selected_set(it, EINA_TRUE);
+
+   _font_preview_update(win);
+}
+
+static void
+_font_styles_list_sel(void *data   __UNUSED__,
+                      Evas_Object *obj,
+                      void        *event_info)
+{
+   Evas_Object *fc_list, *fs_list, *win;
+   Elm_Text_Class_Data *tc_data;
+   const Eina_List *l;
+   Elm_List_Item *it;
+
+   win = elm_object_top_widget_get(obj);
+   fc_list = evas_object_data_get(win, "font_classes_list");
+   fs_list = evas_object_data_get(win, "font_sizes_list");
+
+   it = elm_list_selected_item_get(fc_list);
+   if (!it) return;  /* should not happen */
+
+   eina_stringshare_replace(&fdata.cur_style,
+                            elm_list_item_label_get(event_info));
+   ELM_LIST_ENABLE(fs_list);
+
+   tc_data = elm_list_item_data_get(it);
+   eina_stringshare_del(tc_data->style);
+   tc_data->style = eina_stringshare_ref(fdata.cur_style);
+
+   evas_event_freeze(evas_object_evas_get(fs_list));
+   edje_freeze();
+
+   EINA_LIST_FOREACH(elm_list_items_get(fs_list), l, it)
+     {
+        Elm_Font_Size_Data *sdata;
+
+        sdata = elm_list_item_data_get(it);
+        elm_list_item_selected_set(l->data, EINA_FALSE);
+
+        if (tc_data->size == sdata->size)
+          {
+             elm_list_item_selected_set(it, EINA_TRUE);
+             elm_list_item_show(it);
+             break;
+          }
+     }
+
+   edje_thaw();
+   evas_event_thaw(evas_object_evas_get(fs_list));
+
+   _font_preview_update(win);
+}
+
+static void
+_font_sizes_list_sel(void *data       __UNUSED__,
+                     Evas_Object *obj __UNUSED__,
+                     void *event_info __UNUSED__)
+{
+   Elm_Text_Class_Data *tc_data;
+   Evas_Object *fc_list, *win;
+   Elm_Font_Size_Data *sd;
+   Elm_List_Item *it;
+
+   win = elm_object_top_widget_get(obj);
+   fc_list = evas_object_data_get(win, "font_classes_list");
+
+   it = elm_list_selected_item_get(fc_list);
+   if (!it) return;  /* should not happen */
+
+   sd = elm_list_item_data_get(event_info);
+   fdata.cur_size = sd->size;
+
+   tc_data = elm_list_item_data_get(it);
+   tc_data->size = fdata.cur_size;
+
+   _font_preview_update(win);
+}
+
+static void
+_fstyle_list_unselect_cb(void *data       __UNUSED__,
+                         Evas_Object     *obj,
+                         void *event_info __UNUSED__)
+{
+   Evas_Object *sizes_list, *win;
+
+   if (elm_list_selected_item_get(obj)) return;
+
+   win = elm_object_top_widget_get(obj);
+
+   sizes_list = evas_object_data_get(win, "font_sizes_list");
+   ELM_LIST_DISABLE(sizes_list);
+}
+
+static void
+_fc_list_unselect_cb(void *data       __UNUSED__,
+                     Evas_Object     *obj,
+                     void *event_info __UNUSED__)
+{
+   Evas_Object *font_names_list, *styles_list, *sizes_list, *win;
+
+   if (elm_list_selected_item_get(obj)) return;
+
+   win = elm_object_top_widget_get(obj);
+
+   font_names_list = evas_object_data_get(win, "font_names_list");
+   ELM_LIST_DISABLE(font_names_list);
+
+   styles_list = evas_object_data_get(win, "font_styles_list");
+   ELM_LIST_DISABLE(styles_list);
+
+   sizes_list = evas_object_data_get(win, "font_sizes_list");
+   ELM_LIST_DISABLE(sizes_list);
+}
+
+static void
+_font_classes_list_load(Evas_Object *li)
+{
+   Elm_Text_Class_Data *tc_data;
+   Eina_List *l;
+   Evas *evas;
+
+   evas = evas_object_evas_get(li);
+   evas_event_freeze(evas);
+   edje_freeze();
+
+   EINA_LIST_FOREACH(fdata.text_classes, l, tc_data)
+     elm_list_item_append(li, tc_data->desc, NULL, NULL,
+                          _font_classes_list_sel, tc_data);
+
+   evas_object_smart_callback_add(li, "unselected", _fc_list_unselect_cb,
+                                  NULL);
+
+   elm_list_go(li);
+   edje_thaw();
+   evas_event_thaw(evas);
+}
+
+static void
+_fonts_data_fill(Evas *evas)
+{
+   const Eina_List *fo_list, *text_classes, *l;
+   Elm_Text_Class_Data *tc_data;
+   Elm_Font_Size_Data *sd;
+   Elm_Font_Overlay *efo;
+   Eina_List *evas_fonts;
+   Elm_Text_Class *etc;
+   int i;
+
+   evas_fonts = evas_font_available_list(evas);
+   fdata.font_hash = elm_font_available_hash_add(evas_fonts);
+   evas_font_available_list_free(evas, evas_fonts);
+
+   text_classes = elm_text_classes_list_get();
+   fo_list = elm_font_overlay_list_get();
+
+   EINA_LIST_FOREACH(text_classes, l, etc)
+     {
+        const Eina_List *ll;
+
+        tc_data = calloc(1, sizeof(*tc_data));
+        tc_data->name = eina_stringshare_add(etc->name);
+        tc_data->desc = eina_stringshare_add(etc->desc);
+
+        EINA_LIST_FOREACH(fo_list, ll, efo)
+          {
+             if (strcmp(tc_data->name, efo->text_class))
+               continue;
+
+             if (efo->font)
+               {
+                  Elm_Font_Properties *efp;
+
+                  efp = elm_font_properties_get(efo->font);
+                  if (efp)
+                    {
+                       tc_data->font = eina_stringshare_add(efp->name);
+                       /* we're sure we recorded with only 1 style selected */
+                       tc_data->style = eina_stringshare_add(efp->styles->data);
+                       elm_font_properties_free(efp);
+                    }
+               }
+             tc_data->size = efo->size;
+          }
+
+        fdata.text_classes = eina_list_append(fdata.text_classes, tc_data);
+     }
+
+   elm_text_classes_list_free(text_classes);
+
+   /* FIXME: hinting later */
+   /* fdata.hinting = e_config->font_hinting; */
+
+   sd = calloc(1, sizeof(Elm_Font_Size_Data));
+   sd->size_str = eina_stringshare_add("Tiny");
+   sd->size = -50;
+   fdata.font_scale_list = eina_list_append(fdata.font_scale_list, sd);
+
+   sd = calloc(1, sizeof(Elm_Font_Size_Data));
+   sd->size_str = eina_stringshare_add("Small");
+   sd->size = -80;
+   fdata.font_scale_list = eina_list_append(fdata.font_scale_list, sd);
+
+   sd = calloc(1, sizeof(Elm_Font_Size_Data));
+   sd->size_str = eina_stringshare_add("Normal");
+   sd->size = -100;
+   fdata.font_scale_list = eina_list_append(fdata.font_scale_list, sd);
+
+   sd = calloc(1, sizeof(Elm_Font_Size_Data));
+   sd->size_str = eina_stringshare_add("Big");
+   sd->size = -150;
+   fdata.font_scale_list = eina_list_append(fdata.font_scale_list, sd);
+
+   sd = calloc(1, sizeof(Elm_Font_Size_Data));
+   sd->size_str = eina_stringshare_add("Really Big");
+   sd->size = -190;
+   fdata.font_scale_list = eina_list_append(fdata.font_scale_list, sd);
+
+   sd = calloc(1, sizeof(Elm_Font_Size_Data));
+   sd->size_str = eina_stringshare_add("Huge");
+   sd->size = -250;
+   fdata.font_scale_list = eina_list_append(fdata.font_scale_list, sd);
+
+   for (i = 5; i < 51; i++)
+     {
+        char str[16];
+
+        str[0] = 0;
+        snprintf(str, sizeof(str), "%d pixels", i);
+
+        sd = calloc(1, sizeof(Elm_Font_Size_Data));
+        sd->size_str = eina_stringshare_add(str);
+        sd->size = i;
+        fdata.font_px_list = eina_list_append(fdata.font_px_list, sd);
+     }
+}
+
+static int
+_font_sort_cb(const void *data1,
+              const void *data2)
+{
+   if (!data1) return 1;
+   if (!data2) return -1;
+   return strcmp(data1, data2);
+}
+
+static void
+_font_sizes_list_load(Evas_Object *size_list)
+{
+   Elm_Font_Size_Data *size_data;
+   Eina_List *l;
+   Evas *evas;
+
+   evas = evas_object_evas_get(size_list);
+   evas_event_freeze(evas);
+   edje_freeze();
+
+   EINA_LIST_FOREACH(fdata.font_scale_list, l, size_data)
+     elm_list_item_append(size_list, size_data->size_str, NULL, NULL,
+                          _font_sizes_list_sel, size_data);
+
+   EINA_LIST_FOREACH(fdata.font_px_list, l, size_data)
+     elm_list_item_append(size_list, size_data->size_str, NULL, NULL,
+                          _font_sizes_list_sel, size_data);
+
+   elm_list_go(size_list);
+   edje_thaw();
+   evas_event_thaw(evas);
+}
+
+static void
+_fnames_list_unselect_cb(void *data       __UNUSED__,
+                         Evas_Object     *obj,
+                         void *event_info __UNUSED__)
+{
+   Evas_Object *styles_list, *sizes_list, *win;
+
+   if (elm_list_selected_item_get(obj)) return;
+
+   win = elm_object_top_widget_get(obj);
+
+   styles_list = evas_object_data_get(win, "font_styles_list");
+   ELM_LIST_DISABLE(styles_list);
+
+   sizes_list = evas_object_data_get(win, "font_sizes_list");
+   ELM_LIST_DISABLE(sizes_list);
+}
+
+static Eina_Bool
+_font_list_fill(const Eina_Hash *hash __UNUSED__,
+                const void *key       __UNUSED__,
+                void                 *data,
+                void                 *fdata)
+{
+   Elm_Font_Properties *efp;
+   Eina_List **flist;
+
+   flist = fdata;
+   efp = data;
+
+   *flist = eina_list_append(*flist, efp->name);
+
+   return EINA_TRUE;
+}
+
+static void
+_font_names_list_load(Evas_Object *flist)
+{
+   Eina_List *l, *names_list = NULL;
+   const char *font;
+   Evas *evas;
+
+   evas = evas_object_evas_get(flist);
+   evas_event_freeze(evas);
+   edje_freeze();
+
+   eina_hash_foreach(fdata.font_hash, _font_list_fill, &names_list);
+   names_list = eina_list_sort(names_list, eina_list_count(names_list),
+                               _font_sort_cb);
+
+   EINA_LIST_FOREACH(names_list, l, font)
+     elm_list_item_append(flist, font, NULL, NULL, _font_names_list_sel, NULL);
+
+   EINA_LIST_FREE(names_list, font) ;
+
+   evas_object_smart_callback_add(flist, "unselected",
+                                  _fnames_list_unselect_cb, NULL);
+
+   elm_list_go(flist);
+
+   edje_thaw();
+   evas_event_thaw(evas);
+}
+
+static void
+_status_config_fonts(Evas_Object *win,
+                     Evas_Object *pager)
+{
+   Evas_Object *base, *fr, *li, *rc, *preview, *sp, *pd, *bt, *bx;
+   char buf[PATH_MAX];
+
+   _fonts_data_fill(evas_object_evas_get(win));
+
+   base = elm_table_add(win);
+   evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(base, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   /* yeah, dummy rectangles are ugly as hell, but no good way yet of
+      fixing sizes */
+   rc = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_size_hint_min_set(rc, 70, 170);
+   elm_table_pack(base, rc, 1, 0, 1, 1);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Font Class");
+   elm_table_pack(base, fr, 0, 0, 1, 2);
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(fr);
+
+   /* FIXME: no multiselection for this list, for now */
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, li);
+   evas_object_show(li);
+
+   evas_object_data_set(win, "font_classes_list", li);
+   _font_classes_list_load(li);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Font");
+   elm_table_pack(base, fr, 1, 0, 1, 2);
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(fr);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, li);
+   evas_object_show(li);
+
+   evas_object_data_set(win, "font_names_list", li);
+   _font_names_list_load(li);
+   ELM_LIST_DISABLE(li);
+
+   rc = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_size_hint_min_set(rc, 70, 130);
+   elm_table_pack(base, rc, 1, 2, 1, 1);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Style");
+   elm_table_pack(base, fr, 0, 2, 1, 1);
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(fr);
+   ELM_LIST_DISABLE(li);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, li);
+   evas_object_show(li);
+
+   evas_object_data_set(win, "font_styles_list", li);
+   evas_object_smart_callback_add(li, "unselected", _fstyle_list_unselect_cb,
+                                  NULL);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Size");
+   elm_table_pack(base, fr, 1, 2, 1, 1);
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(fr);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, li);
+   evas_object_show(li);
+
+   evas_object_data_set(win, "font_sizes_list", li);
+   _font_sizes_list_load(li);
+   ELM_LIST_DISABLE(li);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(base, bx, 0, 3, 2, 1);
+   evas_object_show(bx);
+
+   /* FIXME: what to do here? dedicated widget? some new entry API set? */
+   snprintf(buf, sizeof(buf), "%s/objects/font_preview.edj", PACKAGE_DATA_DIR);
+   preview = elm_layout_add(win);
+   elm_layout_file_set(preview, buf, "font_preview");
+   elm_layout_text_set(preview, "elm.text", "Preview Text — 我真的会写中文");
+   evas_object_size_hint_weight_set(preview, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(preview, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(preview);
+
+   elm_box_pack_end(bx, preview);
+   evas_object_data_set(win, "font_preview", elm_layout_edje_get(preview));
+
+   /////////////////////////////////////////////
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, EINA_TRUE);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_table_pack(base, sp, 0, 4, 2, 1);
+   evas_object_show(sp);
+
+   pd = elm_frame_add(win);
+   elm_object_style_set(pd, "pad_medium");
+   evas_object_size_hint_weight_set(pd, 0.0, 0.0);
+   evas_object_size_hint_align_set(pd, 0.5, 0.5);
+   elm_table_pack(base, pd, 0, 5, 2, 1);
+   evas_object_show(pd);
+
+   bx = elm_box_add(win);
+   elm_box_horizontal_set(bx, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(bx);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _font_overlay_set_all, win);
+   elm_button_label_set(bt, "Set to All");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _font_overlay_reset, win);
+   elm_button_label_set(bt, "Reset");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _font_overlay_reset_all, win);
+   elm_button_label_set(bt, "Reset All");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _font_overlay_change, win);
+   elm_button_label_set(bt, "Apply");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   elm_frame_content_set(pd, bx);
+
+   evas_object_data_set(win, "fonts", base);
+
+   elm_pager_content_push(pager, base);
+}
+
+static void
+_engines_list_item_del_cb(void            *data,
+                          Evas_Object *obj __UNUSED__,
+                          void *event_info __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_profiles_list_item_del_cb(void            *data,
+                           Evas_Object *obj __UNUSED__,
+                           void *event_info __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_profiles_list_selected_cb(void            *data,
+                           Evas_Object     *obj,
+                           void *event_info __UNUSED__)
+{
+   const char *cur_profile = NULL;
+   const char *sel_profile, *pdir;
+   Eina_Bool cur_selected;
+   const char *prof_name;
+   char buf[PATH_MAX];
+   Evas_Object *en;
+#ifdef ELM_EFREET
+   Efreet_Desktop *desk = NULL;
+#endif
+
+   sel_profile = data;
+   if (!sel_profile)
+     return;
+
+   cur_profile = elm_profile_current_get();
+   cur_selected = !strcmp(cur_profile, sel_profile);
+
+   pdir = elm_profile_dir_get(sel_profile, EINA_FALSE);
+#ifdef ELM_EFREET
+   snprintf(buf, sizeof(buf), "%s/profile.desktop", pdir);
+   desk = efreet_desktop_new(buf);
+   if ((desk) && (desk->name)) prof_name = desk->name;
+   else
+#endif
+   prof_name = cur_profile;
+
+   if (!pdir)
+     elm_object_disabled_set(evas_object_data_get(obj, "prof_reset_btn"),
+                             EINA_TRUE);
+   else
+     {
+        elm_object_disabled_set(evas_object_data_get(obj, "prof_del_btn"),
+                                EINA_TRUE);
+        elm_object_disabled_set(evas_object_data_get(obj, "prof_reset_btn"),
+                                EINA_FALSE);
+        elm_object_disabled_set(evas_object_data_get(obj, "prof_use_btn"),
+                                EINA_FALSE);
+        elm_profile_dir_free(pdir);
+     }
+
+   snprintf(buf, sizeof(buf), "<hilight>Selected profile: %s</><br>",
+            prof_name);
+   elm_label_label_set(evas_object_data_get(obj, "prof_name_lbl"), buf);
+
+   en = evas_object_data_get(obj, "prof_desc_entry");
+#ifdef ELM_EFREET
+   if (desk) elm_scrolled_entry_entry_set(en, desk->comment);
+   else
+#endif
+   elm_scrolled_entry_entry_set(en, "Unknown");
+
+#ifdef ELM_EFREET
+   if (desk) efreet_desktop_free(desk);
+#endif
+}
+
+static void
+_profiles_list_fill(Evas_Object *l_widget,
+                    Eina_List   *p_names)
+{
+   const char *cur_profile = NULL;
+   const char *profile;
+   void *sel_it = NULL;
+   Eina_List *l;
+
+   if (!p_names)
+     return;
+
+   elm_list_clear(l_widget);
+
+   cur_profile = elm_profile_current_get();
+
+   EINA_LIST_FOREACH(p_names, l, profile)
+     {
+#ifdef ELM_EFREET
+        Efreet_Desktop *desk = NULL;
+#endif
+        const char *label, *ext, *pdir;
+        char buf[PATH_MAX];
+        Elm_List_Item *it;
+        Evas_Object *ic;
+
+        pdir = elm_profile_dir_get(profile, EINA_FALSE);
+        label = profile;
+
+#ifdef ELM_EFREET
+        snprintf(buf, sizeof(buf), "%s/profile.desktop", pdir);
+        desk = efreet_desktop_new(buf);
+        if ((desk) && (desk->name)) label = desk->name;
+#endif
+
+        buf[0] = 0;
+        if (pdir) snprintf(buf, sizeof(buf), "%s/icon.edj", pdir);
+#ifdef ELM_EFREET
+        if ((desk) && (desk->icon) && (pdir))
+          snprintf(buf, sizeof(buf), "%s/%s", pdir, desk->icon);
+#endif
+        ic = elm_icon_add(l_widget);
+        ext = strrchr(buf, '.');
+        if (ext)
+          {
+             if (!strcmp(ext, ".edj")) elm_icon_file_set(ic, buf, "icon");
+             else elm_icon_file_set(ic, buf, NULL);
+          }
+
+        evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL,
+                                         1, 1);
+        evas_object_show(ic);
+
+        it = elm_list_item_append(l_widget, label, ic, NULL,
+                                  _profiles_list_selected_cb, strdup(profile));
+        elm_list_item_del_cb_set(it, _profiles_list_item_del_cb);
+        if (cur_profile && !strcmp(profile, cur_profile))
+          sel_it = it;
+
+        elm_profile_dir_free(pdir);
+
+#ifdef ELM_EFREET
+        if (desk) efreet_desktop_free(desk);
+#endif
+     }
+
+   if (sel_it) elm_list_item_selected_set(sel_it, EINA_TRUE);
+   elm_list_go(l_widget);
+}
+
+static void
+_profiles_list_unselect_cb(void *data       __UNUSED__,
+                           Evas_Object     *obj,
+                           void *event_info __UNUSED__)
+{
+   if (elm_list_selected_item_get(obj)) return;
+   elm_object_disabled_set(evas_object_data_get(obj, "prof_del_btn"),
+                           EINA_TRUE);
+   elm_object_disabled_set(evas_object_data_get(obj, "prof_reset_btn"),
+                           EINA_TRUE);
+   elm_object_disabled_set(evas_object_data_get(obj, "prof_use_btn"),
+                           EINA_TRUE);
+}
+
+static void
+_status_config_profiles(Evas_Object *win,
+                        Evas_Object *pager)
+{
+   Evas_Object *li, *bx, *fr_bx1, *fr_bx2, *btn_bx, *fr, *lb, *en, *sp, *pd,
+   *bt;
+   Eina_List *profs;
+   Evas *evas;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   fr_bx1 = elm_box_add(win);
+   evas_object_size_hint_weight_set(fr_bx1, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr_bx1, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_homogenous_set(fr_bx1, EINA_TRUE);
+   evas_object_show(fr_bx1);
+
+   fr_bx2 = elm_box_add(win);
+   evas_object_size_hint_weight_set(fr_bx2, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr_bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(fr_bx2);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Available Profiles");
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, fr_bx1);
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(li, "unselected", _profiles_list_unselect_cb,
+                                  NULL);
+
+   profs = elm_profile_list_get();
+
+   evas_object_show(li);
+   elm_box_pack_end(fr_bx2, li);
+
+   lb = elm_label_add(win);
+   evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, 0.5);
+
+   evas_object_show(lb);
+
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_editable_set(en, EINA_FALSE);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(en);
+
+   evas_object_data_set(li, "prof_name_lbl", lb);
+   evas_object_data_set(li, "prof_desc_entry", en);
+
+   elm_box_pack_end(fr_bx2, lb);
+   elm_box_pack_end(fr_bx1, fr_bx2);
+   elm_box_pack_end(fr_bx1, en);
+
+   /////////////////////////////////////////////
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, EINA_TRUE);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   pd = elm_frame_add(win);
+   elm_object_style_set(pd, "pad_medium");
+   evas_object_size_hint_weight_set(pd, 0.0, 0.0);
+   evas_object_size_hint_align_set(pd, 0.5, 0.5);
+   elm_box_pack_end(bx, pd);
+   evas_object_show(pd);
+
+   btn_bx = elm_box_add(win);
+   elm_box_horizontal_set(btn_bx, EINA_TRUE);
+   evas_object_size_hint_weight_set(btn_bx, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(btn_bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(btn_bx);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _profile_use, li);
+   elm_button_label_set(bt, "Use");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(btn_bx, bt);
+   evas_object_show(bt);
+
+   evas_object_data_set(li, "prof_use_btn", bt);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _btn_todo, NULL); /* TODO */
+   elm_button_label_set(bt, "Delete");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(btn_bx, bt);
+   evas_object_show(bt);
+
+   evas_object_data_set(li, "prof_del_btn", bt);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _profile_reset, li);
+   elm_button_label_set(bt, "Reset");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(btn_bx, bt);
+   evas_object_show(bt);
+
+   evas_object_data_set(li, "prof_reset_btn", bt);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _btn_todo, NULL); /* TODO */
+   elm_button_label_set(bt, "Add new");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(btn_bx, bt);
+   evas_object_show(bt);
+
+   elm_frame_content_set(pd, btn_bx);
+
+   evas = evas_object_evas_get(li);
+   evas_event_freeze(evas);
+   edje_freeze();
+
+   _profiles_list_fill(li, profs);
+
+   elm_profile_list_free(profs);
+
+   edje_thaw();
+   evas_event_thaw(evas);
+
+   evas_object_data_set(win, "profiles", bx);
+   elm_pager_content_push(pager, bx);
+}
+
+static void
+_status_config_scrolling(Evas_Object *win,
+                         Evas_Object *pager)
+{
+   Evas_Object *lb, *pd, *bx, *sl, *sp, *ck, *sc;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
+
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scroller_bounce_set(sc, EINA_FALSE, EINA_TRUE);
+   evas_object_show(sc);
+   elm_scroller_content_set(sc, bx);
+
+   ck = elm_check_add(win);
+   elm_object_tooltip_text_set(ck, "Set whether scrollers should bounce<br>"
+                                   "when they reach their viewport's edge<br>"
+                                   "during a scroll");
+   elm_check_label_set(ck, "Enable scroll bounce");
+   evas_object_data_set(win, "scroll_bounce_check", ck);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(ck, EVAS_HINT_FILL, 0.5);
+   elm_check_state_set(ck, elm_scroll_bounce_enabled_get());
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   evas_object_smart_callback_add(ck, "changed", sb_change, NULL);
+
+   LABEL_FRAME_ADD("<hilight>Scroll bounce friction</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the amount of inertia a <br>"
+                                   "scroller will impose at bounce animations");
+   evas_object_data_set(win, "bounce_friction_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.2f");
+   elm_slider_indicator_format_set(sl, "%1.2f");
+   elm_slider_min_max_set(sl, 0.0, 4.0);
+   elm_slider_value_set(sl, elm_scroll_bounce_friction_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", bf_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", bf_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, EINA_TRUE);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   ck = elm_check_add(win);
+   elm_object_tooltip_text_set(ck, "Set whether scrollers should be<br>"
+                                   "draggable from any point in their views");
+   elm_check_label_set(ck, "Enable thumb scroll");
+   evas_object_data_set(win, "thumbscroll_check", ck);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(ck, EVAS_HINT_FILL, 0.5);
+   elm_check_state_set(ck, elm_scroll_thumbscroll_enabled_get());
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   evas_object_smart_callback_add(ck, "changed", ts_change, NULL);
+
+   LABEL_FRAME_ADD("<hilight>Thumb scroll threshold</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the number of pixels one should<br>"
+                                   "travel while dragging a scroller's view<br>"
+                                   "to actually trigger scrolling");
+   evas_object_data_set(win, "thumbscroll_threshold_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f pixels");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 8.0, 50.0);
+   elm_slider_value_set(sl, elm_scroll_thumbscroll_threshold_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", tst_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", tst_change, NULL);
+
+   LABEL_FRAME_ADD("<hilight>Thumb scroll momentum threshold</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the minimum speed of mouse <br>"
+                                   "cursor movement which will trigger<br>"
+                                   "list self scrolling animation after a<br>"
+                                   "mouse up event (pixels/second)");
+   evas_object_data_set(win, "ts_momentum_threshold_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f pixels/s");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 10.0, 200.0);
+   elm_slider_value_set(sl, elm_scroll_thumbscroll_momentum_threshold_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", tsmt_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", tsmt_change,
+                                  NULL);
+
+   LABEL_FRAME_ADD("<hilight>Thumb scroll friction</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the amount of inertia a<br>"
+                                   "scroller will impose at self scrolling<br>"
+                                   "animations");
+   evas_object_data_set(win, "thumbscroll_friction_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.1f");
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_min_max_set(sl, 0.0, 15.0);
+   elm_slider_value_set(sl, elm_scroll_thumbscroll_friction_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", tsf_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", tsf_change, NULL);
+
+   LABEL_FRAME_ADD("<hilight>Thumb scroll border friction</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the amount of lag between your<br>"
+                                   "actual mouse cursor dragging movement<br>"
+                                   "and a scroller's view movement itself,<br>"
+                                   "while pushing it into bounce state<br>"
+                                   "manually");
+   evas_object_data_set(win, "ts_border_friction_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.2f");
+   elm_slider_indicator_format_set(sl, "%1.2f");
+   elm_slider_min_max_set(sl, 0.0, 1.0);
+   elm_slider_value_set(sl, elm_scroll_thumbscroll_border_friction_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", tsbf_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", tsbf_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, EINA_TRUE);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   LABEL_FRAME_ADD("<hilight>Page scroll friction</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the amount of inertia a<br>"
+                                   "paged scroller will impose at<br>"
+                                   "page fitting animations");
+   evas_object_data_set(win, "page_scroll_friction_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.1f");
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_min_max_set(sl, 0.0, 5.0);
+   elm_slider_value_set(sl, elm_scroll_page_scroll_friction_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", ps_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", ps_change, NULL);
+
+   LABEL_FRAME_ADD("<hilight>Bring in scroll friction</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the amount of inertia a<br>"
+                                   "scroller will impose at region bring<br>"
+                                   "animations");
+   evas_object_data_set(win, "bring_in_scroll_friction_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.1f");
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_min_max_set(sl, 0.0, 5.0);
+   elm_slider_value_set(sl, elm_scroll_bring_in_scroll_friction_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", bis_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", bis_change, NULL);
+
+   LABEL_FRAME_ADD("<hilight>Zoom scroll friction</>");
+
+   sl = elm_slider_add(win);
+   elm_object_tooltip_text_set(sl, "This is the amount of inertia<br>"
+                                   "scrollers will impose at animations<br>"
+                                   "triggered by Elementary widgets'<br>"
+                                   "zooming API");
+   evas_object_data_set(win, "zoom_scroll_friction_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.1f");
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_min_max_set(sl, 0.0, 5.0);
+   elm_slider_value_set(sl, elm_scroll_zoom_friction_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", zf_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", zf_change, NULL);
+
+   evas_object_data_set(win, "scrolling", sc);
+
+   elm_pager_content_push(pager, sc);
+}
+
+static char *
+_engine_name_prettify(const char *engine)
+{
+   char *ret, *ptr;
+
+   ret = strdup(engine);
+   ret[0] -= 0x20;
+
+   while ((ptr = strpbrk(ret, "_")))
+     {
+        *ptr = ' ';
+     }
+
+   return ret;
+}
+
+/* FIXME! ideally, we would trim elm_config.c's _elm_engines list at
+   build time, making a getter for is as in ecore-evas. */
+static Eina_Bool
+_elm_engine_supported(const char *engine)
+{
+   const char *engines[] = {
+      "software_x11",
+      "fb",
+      "directfb",
+      "software_16_x11",
+      "software_8_x11",
+      "xrender_x11",
+      "opengl_x11",
+      "software_gdi",
+      "software_16_wince_gdi",
+      "sdl",
+      "software_16_sdl",
+      "opengl_sdl",
+      NULL
+   };
+
+   unsigned int i;
+
+   for (i = 0; engines[i]; i++)
+     {
+#define ENGINE_COMPARE(name) (!strcmp(engines[i], name))
+        if (ENGINE_COMPARE(engine))
+          return EINA_TRUE;
+#undef ENGINE_COMPARE
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_engines_list_fill(Evas_Object *l_widget,
+                   Eina_List   *e_names)
+{
+   const char *engine, *cur_engine;
+   void *sel_it = NULL;
+   Eina_List *l;
+
+   if (!e_names)
+     return;
+
+   cur_engine = elm_engine_current_get();
+
+   EINA_LIST_FOREACH(e_names, l, engine)
+     {
+        const char *label;
+        Elm_List_Item *it;
+
+        if (!_elm_engine_supported(engine))
+          continue;
+
+        label = _engine_name_prettify(engine);
+
+        it = elm_list_item_append(l_widget, label, NULL, NULL, NULL,
+                                  strdup(engine));
+        elm_list_item_del_cb_set(it, _engines_list_item_del_cb);
+        free((void *)label);
+
+        if (!strcmp(cur_engine, engine))
+          sel_it = it;
+     }
+
+   if (sel_it) elm_list_item_selected_set(sel_it, EINA_TRUE);
+   elm_list_go(l_widget);
+}
+
+static void
+_status_config_rendering(Evas_Object *win,
+                         Evas_Object *pager)
+{
+   Evas_Object *li, *bx, *fr, *sp, *pd, *bt;
+   Eina_List *engines;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Available Engines");
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   li = elm_list_add(win);
+   elm_frame_content_set(fr, li);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   engines = ecore_evas_engines_get();
+   _engines_list_fill(li, engines);
+   ecore_evas_engines_free(engines);
+
+   evas_object_show(li);
+   evas_object_data_set(win, "engines_list", li);
+
+   /////////////////////////////////////////////
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, EINA_TRUE);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   pd = elm_frame_add(win);
+   elm_object_style_set(pd, "pad_medium");
+   evas_object_size_hint_weight_set(pd, 0.0, 0.0);
+   evas_object_size_hint_align_set(pd, 0.5, 0.5);
+   elm_box_pack_end(bx, pd);
+   evas_object_show(pd);
+
+   bt = elm_button_add(win);
+   evas_object_smart_callback_add(bt, "clicked", _engine_use, li);
+   elm_button_label_set(bt, "Use Engine");
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_frame_content_set(pd, bt);
+   evas_object_show(bt);
+
+   evas_object_data_set(win, "rendering", bx);
+   elm_pager_content_push(pager, bx);
+}
+
+static void
+_status_config_caches(Evas_Object *win,
+                      Evas_Object *pager)
+{
+   Evas_Object *lb, *pd, *bx, *sl, *sp, *ck;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
+
+   LABEL_FRAME_ADD("<hilight>Cache Flush Interval (8 ticks pre second)</>");
+
+   sl = elm_slider_add(win);
+   evas_object_data_set(win, "cache_flush_interval_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f ticks");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 8.0, 4096.0);
+   elm_slider_value_set(sl, elm_cache_flush_interval_get());
+   elm_object_disabled_set(sl, !elm_cache_flush_enmabled_get());
+
+   ck = elm_check_add(win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(ck, EVAS_HINT_FILL, 0.5);
+   elm_check_label_set(ck, "Enable Flushing");
+   elm_check_state_set(ck, elm_cache_flush_enmabled_get());
+   evas_object_smart_callback_add(ck, "changed", cf_enable, sl);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+   
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+   
+   evas_object_smart_callback_add(sl, "changed", cf_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", cf_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   LABEL_FRAME_ADD("<hilight>Font Cache Size</>");
+
+   sl = elm_slider_add(win);
+   evas_object_data_set(win, "font_cache_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.1f MB");
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_min_max_set(sl, 0.0, 4.0);
+   elm_slider_value_set(sl, (double)elm_font_cache_get() / 1024.0);
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", fc_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", fc_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   LABEL_FRAME_ADD("<hilight>Image Cache Size</>");
+
+   sl = elm_slider_add(win);
+   evas_object_data_set(win, "image_cache_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f MB");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 0, 32);
+   elm_slider_value_set(sl, (double)elm_image_cache_get() / 1024.0);
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", ic_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", ic_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   LABEL_FRAME_ADD("<hilight>Number of Edje Files to Cache</>");
+
+   sl = elm_slider_add(win);
+   evas_object_data_set(win, "edje_file_cache_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f files");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 0, 32);
+   elm_slider_value_set(sl, elm_edje_file_cache_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", efc_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", efc_change, NULL);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   LABEL_FRAME_ADD("<hilight>Number of Edje Collections to Cache</>");
+
+   sl = elm_slider_add(win);
+   evas_object_data_set(win, "edje_collection_cache_slider", sl);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_unit_format_set(sl, "%1.0f collections");
+   elm_slider_indicator_format_set(sl, "%1.0f");
+   elm_slider_min_max_set(sl, 0, 128);
+   elm_slider_value_set(sl, elm_edje_collection_cache_get());
+   elm_box_pack_end(bx, sl);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl, "changed", ecc_round, NULL);
+   evas_object_smart_callback_add(sl, "delay,changed", ecc_change, NULL);
+
+   evas_object_data_set(win, "caches", bx);
+
+   elm_pager_content_push(pager, bx);
+}
+
+static void
+_status_config_full(Evas_Object *win,
+                    Evas_Object *bx0)
+{
+   Evas_Object *tb, *pager;
+   Elm_Toolbar_Item *sizing, *it;
+
+   tb = elm_toolbar_add(win);
+   elm_toolbar_menu_parent_set(tb, win);
+   elm_toolbar_homogenous_set(tb, 0);
+   evas_object_size_hint_weight_set(tb, 1.0, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   sizing = elm_toolbar_item_append(tb, "zoom-fit-best", "Sizing",
+                                    _cf_sizing, win);
+   elm_toolbar_item_priority_set(sizing, 100);
+
+   it = elm_toolbar_item_append(tb, "preferences-desktop-theme", "Theme",
+                                _cf_themes, win);
+   elm_toolbar_item_priority_set(it, 90);
+
+   elm_toolbar_item_append(tb, "preferences-desktop-font", "Fonts",
+                           _cf_fonts, win);
+
+   it = elm_toolbar_item_append(tb, "system-users", "Profiles",
+                                _cf_profiles, win);
+   elm_toolbar_item_priority_set(it, 90);
+
+   elm_toolbar_item_append(tb, "system-run", "Scrolling", _cf_scrolling, win);
+   elm_toolbar_item_append(tb, "video-display", "Rendering",
+                           _cf_rendering, win);
+   elm_toolbar_item_append(tb, "appointment-new", "Caches", _cf_caches, win);
+
+   elm_box_pack_end(bx0, tb);
+   evas_object_show(tb);
+
+   pager = elm_pager_add(win);
+   evas_object_size_hint_align_set(pager, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(pager, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_data_set(win, "pager", pager);
+
+   _status_config_themes(win, pager);
+   _status_config_fonts(win, pager);
+   _status_config_profiles(win, pager);
+   _status_config_rendering(win, pager);
+   _status_config_scrolling(win, pager);
+   _status_config_caches(win, pager);
+   _status_config_sizing(win, pager);
+
+   // FIXME uncomment after flip style fix, please
+   //elm_object_style_set(pager, "flip");
+   elm_toolbar_item_selected_set(sizing, EINA_TRUE);
+   elm_box_pack_end(bx0, pager);
+   evas_object_show(pager);
+}
+
+static void
+status_win(void)
+{
+   Evas_Object *win, *bg, *bx0;
+
+   win = elm_win_add(NULL, "main", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Elementary Config");
+
+   evas_object_smart_callback_add(win, "delete,request", config_exit, NULL);
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, 1.0, 1.0);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   bx0 = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx0, 1.0, 1.0);
+   elm_win_resize_object_add(win, bx0);
+   evas_object_show(bx0);
+
+   if (!interactive) _status_basic(win, bx0);
+   else if (0)
+     _status_config(win, bx0);
+   else _status_config_full(win, bx0);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+static Eina_Bool
+_exit_timer(void *data __UNUSED__)
+{
+   elm_exit();
+   return ECORE_CALLBACK_CANCEL;
+}
+
+/* this is your elementary main function - it MUST be called IMMEDIATELY
+ * after elm_init() and MUST be passed argc and argv, and MUST be called
+ * elm_main and not be static - must be a visible symbol with EAPI infront */
+EAPI int
+elm_main(int    argc,
+         char **argv)
+{
+   int i;
+
+   for (i = 1; i < argc; i++)
+     {
+        if (!strcmp(argv[i], "-h"))
+          {
+             printf("Usage:\n"
+                    "  -h                This help\n"
+                    "  -q                Quiet mode (dont show window)\n"
+                    "  -t THEME          Set theme to THEME (ELM_THEME spec)\n"
+                    "  -f SIZE           Set finger size to SIZE pixels\n"
+                    "  -s SCALE          Set scale factor to SCALE\n"
+                    );
+          }
+        else if (!strcmp(argv[i], "-q"))
+          {
+             quiet = 1;
+             interactive = 0;
+          }
+        else if ((!strcmp(argv[i], "-t")) && (i < argc - 1))
+          {
+             i++;
+             theme_set = argv[i];
+             interactive = 0;
+          }
+        else if ((!strcmp(argv[i], "-f")) && (i < argc - 1))
+          {
+             i++;
+             finger_size_set = argv[i];
+             interactive = 0;
+          }
+        else if ((!strcmp(argv[i], "-s")) && (i < argc - 1))
+          {
+             i++;
+             scale_set = argv[i];
+             interactive = 0;
+          }
+     }
+   /* put here any init code specific to this app like parsing args, etc. */
+   if (!quiet)
+     {
+#ifdef ELM_EFREET
+        elm_need_efreet();
+#endif
+        status_win(); /* create main window */
+        if (!interactive)
+          ecore_timer_add(2.0, _exit_timer, NULL);
+     }
+   if (!interactive)
+     {
+        if (theme_set)
+          {
+             elm_theme_all_set(theme_set);
+          }
+        if (finger_size_set)
+          {
+             elm_finger_size_all_set(atoi(finger_size_set));
+          }
+        if (scale_set)
+          {
+             elm_scale_all_set(atof(scale_set));
+          }
+        if (quiet)
+          {
+             elm_exit();
+          }
+     }
+   elm_run(); /* and run the program now and handle all events, etc. */
+   /* if the mainloop that elm_run() runs exists, we exit the app */
+   elm_shutdown(); /* clean up and shut down */
+   /* exit code */
+   return 0;
+}
+
+#endif
+/* All emelentary apps should use this. Put it right after elm_main() */
+ELM_MAIN()
diff --git a/src/bin/quicklaunch.c b/src/bin/quicklaunch.c
new file mode 100644 (file)
index 0000000..50f26ec
--- /dev/null
@@ -0,0 +1,297 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+static double restart_time = 0.0;
+
+#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
+
+static struct sigaction old_sigint;
+static struct sigaction old_sigterm;
+static struct sigaction old_sigquit;
+static struct sigaction old_sigalrm;
+static struct sigaction old_sigusr1;
+static struct sigaction old_sigusr2;
+static struct sigaction old_sighup;
+static struct sigaction old_sigchld;
+static struct sigaction old_sigsegv;
+static struct sigaction old_sigill;
+static struct sigaction old_sigfpe;
+static struct sigaction old_sigbus;
+static struct sigaction old_sigabrt;
+static int _log_dom = -1;
+
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
+#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
+
+static void
+post_fork(void *data __UNUSED__)
+{
+   sigaction(SIGINT, &old_sigint, NULL);
+   sigaction(SIGTERM, &old_sigterm, NULL);
+   sigaction(SIGQUIT, &old_sigquit, NULL);
+   sigaction(SIGALRM, &old_sigalrm, NULL);
+   sigaction(SIGUSR1, &old_sigusr1, NULL);
+   sigaction(SIGUSR2, &old_sigusr2, NULL);
+   sigaction(SIGHUP, &old_sighup, NULL);
+   sigaction(SIGCHLD, &old_sigchld, NULL);
+   sigaction(SIGSEGV, &old_sigsegv, NULL);
+   sigaction(SIGILL, &old_sigill, NULL);
+   sigaction(SIGFPE, &old_sigfpe, NULL);
+   sigaction(SIGBUS, &old_sigbus, NULL);
+   sigaction(SIGABRT, &old_sigabrt, NULL);
+   if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
+     {
+       eina_log_domain_unregister(_log_dom);
+       _log_dom = -1;
+     }
+}
+
+static void
+child_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
+{
+   int status;
+   while (waitpid(-1, &status, WNOHANG) > 0);
+}
+
+static void
+crash_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
+{
+   double t;
+
+   ERR("crash detected. restarting.");
+   t = ecore_time_get();
+   if ((t - restart_time) <= 2.0)
+     {
+       CRITICAL("crash too fast - less than 2 seconds. abort restart");
+       exit(-1);
+     }
+   ecore_app_restart();
+}
+
+static void
+handle_run(int fd, unsigned long bytes)
+{
+   unsigned char *buf = NULL;
+   int i;
+   char **argv = NULL;
+   char *cwd;
+   int argc;
+
+   buf = alloca(bytes);
+   if (read(fd, buf, bytes) < 0)
+     {
+       close(fd);
+       return;
+     }
+   close(fd);
+   argc = ((unsigned long *)(buf))[0];
+   argv = (char **)(&(((unsigned long *)(buf))[1]));
+   for (i = 0; i < argc; i++) argv[i] = (char *)(buf + (unsigned long)argv[i]);
+   cwd = argv[argc - 1] + strlen(argv[argc - 1]) + 1;
+   elm_quicklaunch_prepare(argc, argv);
+   elm_quicklaunch_fork(argc, argv, cwd, post_fork, NULL);
+   elm_quicklaunch_cleanup();
+}
+
+int
+main(int argc, char **argv)
+{
+   int sock, socket_unix_len;
+   struct stat st;
+   struct sockaddr_un socket_unix;
+   struct linger lin;
+   char buf[PATH_MAX];
+   struct sigaction action;
+
+   if (!eina_init())
+     {
+       fprintf(stderr, "ERROR: failed to init eina.");
+       exit(-1);
+     }
+   _log_dom = eina_log_domain_register
+     ("elementary_quicklaunch", EINA_COLOR_CYAN);
+   if (_log_dom < 0)
+     {
+       EINA_LOG_ERR("could not register elementary_quicklaunch log domain.");
+       _log_dom = EINA_LOG_DOMAIN_GLOBAL;
+     }
+
+   if (!getenv("DISPLAY"))
+     {
+       CRITICAL("DISPLAY env var not set");
+       exit(-1);
+     }
+   snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i", getuid());
+   if (stat(buf, &st) < 0) mkdir(buf, S_IRUSR | S_IWUSR | S_IXUSR);
+   snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i/%s", getuid(), getenv("DISPLAY"));
+   unlink(buf);
+   sock = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (sock < 0)
+     {
+       CRITICAL("cannot create socket for socket for '%s': %s",
+                buf, strerror(errno));
+       exit(-1);
+     }
+   if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0)
+     {
+       CRITICAL("cannot set close on exec socket for '%s' (fd=%d): %s",
+                buf, sock, strerror(errno));
+       exit(-1);
+     }
+   lin.l_onoff = 1;
+   lin.l_linger = 0;
+   if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
+     {
+       CRITICAL("cannot set linger for socket for '%s' (fd=%d): %s",
+                buf, sock, strerror(errno));
+       exit(-1);
+     }
+   socket_unix.sun_family = AF_UNIX;
+   strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
+   socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
+   if (bind(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
+     {
+       CRITICAL("cannot bind socket for '%s' (fd=%d): %s",
+                buf, sock, strerror(errno));
+       exit(-1);
+     }
+   if (listen(sock, 4096) < 0)
+     {
+       CRITICAL("listen(sock=%d, 4096): %s", sock, strerror(errno));
+       exit(-1);
+     }
+   elm_quicklaunch_mode_set(EINA_TRUE);
+   elm_quicklaunch_init(argc, argv);
+   restart_time = ecore_time_get();
+
+   memset(&action, 0, sizeof(struct sigaction));
+   action.sa_handler = SIG_DFL;
+   action.sa_sigaction = NULL;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGINT, &action, &old_sigint);
+
+   action.sa_handler = SIG_DFL;
+   action.sa_sigaction = NULL;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGTERM, &action, &old_sigterm);
+
+   action.sa_handler = SIG_DFL;
+   action.sa_sigaction = NULL;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGQUIT, &action, &old_sigquit);
+
+   action.sa_handler = SIG_DFL;
+   action.sa_sigaction = NULL;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGALRM, &action, &old_sigalrm);
+
+   action.sa_handler = SIG_DFL;
+   action.sa_sigaction = NULL;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGUSR1, &action, &old_sigusr1);
+
+   action.sa_handler = SIG_DFL;
+   action.sa_sigaction = NULL;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGUSR2, &action, &old_sigusr2);
+
+   action.sa_handler = SIG_DFL;
+   action.sa_sigaction = NULL;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGHUP, &action, &old_sighup);
+
+   action.sa_handler = NULL;
+   action.sa_sigaction = child_handler;
+   action.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGCHLD, &action, &old_sigchld);
+
+   action.sa_handler = NULL;
+   action.sa_sigaction = crash_handler;
+   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGSEGV, &action, &old_sigsegv);
+
+   action.sa_handler = NULL;
+   action.sa_sigaction = crash_handler;
+   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGILL, &action, &old_sigill);
+
+   action.sa_handler = NULL;
+   action.sa_sigaction = crash_handler;
+   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGFPE, &action, &old_sigfpe);
+
+   action.sa_handler = NULL;
+   action.sa_sigaction = crash_handler;
+   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGBUS, &action, &old_sigbus);
+
+   action.sa_handler = NULL;
+   action.sa_sigaction = crash_handler;
+   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
+   sigemptyset(&action.sa_mask);
+   sigaction(SIGABRT, &action, &old_sigabrt);
+
+   for (;;)
+     {
+       int fd;
+       struct sockaddr_un client;
+       socklen_t len;
+
+       elm_quicklaunch_sub_init(argc, argv);
+       elm_quicklaunch_seed();
+       len = sizeof(struct sockaddr_un);
+       fd = accept(sock, (struct sockaddr *)&client, &len);
+       if (fd >= 0)
+         {
+            unsigned long bytes;
+            int num;
+
+            num = read(fd, &bytes, sizeof(unsigned long));
+            if (num == sizeof(unsigned long))
+              {
+                 ecore_app_args_set(argc, (const char **)argv);
+                 handle_run(fd, bytes);
+              }
+         }
+       while (elm_quicklaunch_sub_shutdown() > 0);
+     }
+   elm_quicklaunch_shutdown();
+
+   if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
+     {
+       eina_log_domain_unregister(_log_dom);
+       _log_dom = -1;
+     }
+   eina_shutdown();
+
+   return 0;
+}
diff --git a/src/bin/run.c b/src/bin/run.c
new file mode 100644 (file)
index 0000000..ebd9833
--- /dev/null
@@ -0,0 +1,160 @@
+#include "elementary_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
+
+int
+main(int argc, char **argv)
+{
+   int sock, socket_unix_len, i;
+   struct sockaddr_un socket_unix;
+   char buf[PATH_MAX];
+   struct stat st;
+   char *exe;
+   int we_are_elementary_run = 0;
+   char *disp;
+   char *cwd;
+
+   int sargc, slen;
+   unsigned char *sbuf = NULL, *pos;
+   char **sargv = NULL;
+
+   if (!getcwd(buf, sizeof(buf) - 1))
+     {
+       fprintf(stderr, "elementary_quicklaunch: currect working dir too big.\n");
+       exit(-1);
+     }
+   cwd = strdup(buf);
+   if (!(disp = getenv("DISPLAY")))
+     {
+       fprintf(stderr, "elementary_quicklaunch: DISPLAY env var not set\n");
+       exit(-1);
+     }
+   snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i/%s", getuid(), disp);
+   if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+     {
+       perror("elementary_quicklaunch: socket(AF_UNIX, SOCK_STREAM, 0)");
+       exit(-1);
+     }
+   socket_unix.sun_family = AF_UNIX;
+   strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
+   socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
+   if (connect(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
+     {
+       perror("elementary_quicklaunch: connect(sock, (struct sockaddr *)&socket_unix, socket_unix_len)");
+       printf("elementary_quicklaunch: cannot connect to socket '%s'\n", buf);
+       exit(1);
+     }
+   exe = argv[0];
+   if (!(((exe[0] == '/')) ||
+        ((exe[0] == '.') && (exe[1] == '/')) ||
+        ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/'))))
+     {
+       char *path = getenv("PATH");
+       int exelen = strlen(argv[0]);
+       if (path)
+         {
+            const char *p, *pp;
+
+            p = path;
+            pp = p;
+            exe = NULL;
+            for (;;)
+              {
+                 if ((*p == ':') || (!*p))
+                   {
+                      unsigned int len;
+
+                      len = p - pp;
+                      if (len < (sizeof(buf) - exelen - 3))
+                        {
+                           strncpy(buf, pp, len);
+                           strcpy(buf + len, "/");
+                           strcpy(buf + len + 1, argv[0]);
+                           if (!access(buf, R_OK | X_OK))
+                             {
+                                exe = buf;
+                                break;
+                             }
+                           if (!*p) break;
+                           p++;
+                           pp = p;
+                        }
+                   }
+                 else
+                   {
+                      if (!*p) break;
+                      p++;
+                   }
+              }
+         }
+     }
+   if (exe)
+     {
+       if (!lstat(exe, &st))
+         {
+            if (S_ISLNK(st.st_mode))
+              {
+                 char buf2[PATH_MAX];
+
+                 ssize_t len = readlink(exe, buf2, sizeof(buf2) - 1);
+                 if (len >= 0)
+                   {
+                      char *p;
+                      buf2[len] = 0;
+                      p = strrchr(buf2, '/');
+                      if (p) p++;
+                      else p = buf2;
+                      if (!strncasecmp(p, "elementary_run", 14))
+                        we_are_elementary_run = 1;
+                   }
+              }
+         }
+     }
+   if (we_are_elementary_run)
+     {
+       sargc = argc;
+       sargv = argv;
+     }
+   else
+     {
+       sargc = argc - 1;
+       sargv = &(argv[1]);
+     }
+   slen = sizeof(unsigned long) + sizeof(unsigned long);
+   for (i = 0; i < sargc; i++)
+     {
+       slen += sizeof(unsigned long);
+       slen += strlen(sargv[i]) + 1;
+     }
+   slen += strlen(cwd) + 1;
+   sbuf = alloca(slen);
+   ((unsigned long *)(sbuf))[0] = slen - sizeof(unsigned long);
+   ((unsigned long *)(sbuf))[1] = sargc;
+   pos = (unsigned char *)(&((((unsigned long *)(sbuf))[2 + sargc])));
+   for (i = 0; i < sargc; i++)
+     {
+       ((unsigned long *)(sbuf))[2 + i] =
+         (unsigned long)pos - ((unsigned long)sbuf + sizeof(unsigned long));
+       strcpy((char *)pos, sargv[i]);
+       pos += strlen(sargv[i]) + 1;
+     }
+   strcpy((char *)pos, cwd);
+   if (write(sock, sbuf, slen) < 0)
+     printf("elementary_quicklaunch: cannot write to socket '%s'\n", buf);
+   close(sock);
+   return 0;
+}
diff --git a/src/bin/test.c b/src/bin/test.c
new file mode 100644 (file)
index 0000000..e195fbe
--- /dev/null
@@ -0,0 +1,419 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+/* all tests prototypes */
+void test_bg_plain(void *data, Evas_Object *obj, void *event_info);
+void test_bg_image(void *data, Evas_Object *obj, void *event_info);
+void test_bg_options(void *data, Evas_Object *obj, void *event_info);
+void test_icon(void *data, Evas_Object *obj, void *event_info);
+void test_box_vert(void *data, Evas_Object *obj, void *event_info);
+void test_box_vert2(void *data, Evas_Object *obj, void *event_info);
+void test_box_horiz(void *data, Evas_Object *obj, void *event_info);
+void test_box_transition(void *data, Evas_Object *obj, void *event_info);
+void test_button(void *data, Evas_Object *obj, void *event_info);
+void test_transit(void *data, Evas_Object *obj, void *event_info);
+void test_transit2(void *data, Evas_Object *obj, void *event_info);
+void test_transit3(void *data, Evas_Object *obj, void *event_info);
+void test_transit4(void *data, Evas_Object *obj, void *event_info);
+void test_transit5(void *data, Evas_Object *obj, void *event_info);
+void test_transit6(void *data, Evas_Object *obj, void *event_info);
+void test_transit7(void *data, Evas_Object *obj, void *event_info);
+void test_transit8(void *data, Evas_Object *obj, void *event_info);
+void test_fileselector_button(void *data, Evas_Object *obj, void *event_info);
+void test_fileselector_entry(void *data, Evas_Object *obj, void *event_info);
+void test_toggle(void *data, Evas_Object *obj, void *event_info);
+void test_clock(void *data, Evas_Object *obj, void *event_info);
+void test_clock2(void *data, Evas_Object *obj, void *event_info);
+void test_check(void *data, Evas_Object *obj, void *event_info);
+void test_radio(void *data, Evas_Object *obj, void *event_info);
+void test_layout(void *data, Evas_Object *obj, void *event_info);
+void test_hover(void *data, Evas_Object *obj, void *event_info);
+void test_hover2(void *data, Evas_Object *obj, void *event_info);
+void test_entry(void *data, Evas_Object *obj, void *event_info);
+void test_entry_scrolled(void *data, Evas_Object *obj, void *event_info);
+void test_entry3(void *data, Evas_Object *obj, void *event_info);
+void test_entry4(void *data, Evas_Object *obj, void *event_info);
+void test_entry5(void *data, Evas_Object *obj, void *event_info);
+void test_entry_notepad(void *data, Evas_Object *obj, void *event_info);
+void test_anchorview(void *data, Evas_Object *obj, void *event_info);
+void test_anchorblock(void *data, Evas_Object *obj, void *event_info);
+void test_toolbar(void *data, Evas_Object *obj, void *event_info);
+void test_toolbar2(void *data, Evas_Object *obj, void *event_info);
+void test_toolbar3(void *data, Evas_Object *obj, void *event_info);
+void test_toolbar4(void *data, Evas_Object *obj, void *event_info);
+void test_toolbar5(void *data, Evas_Object *obj, void *event_info);
+void test_hoversel(void *data, Evas_Object *obj, void *event_info);
+void test_list(void *data, Evas_Object *obj, void *event_info);
+void test_list_horizontal(void *data, Evas_Object *obj, void *event_info);
+void test_list2(void *data, Evas_Object *obj, void *event_info);
+void test_list3(void *data, Evas_Object *obj, void *event_info);
+void test_list4(void *data, Evas_Object *obj, void *event_info);
+void test_list5(void *data, Evas_Object *obj, void *event_info);
+void test_inwin(void *data, Evas_Object *obj, void *event_info);
+void test_inwin2(void *data, Evas_Object *obj, void *event_info);
+void test_scaling(void *data, Evas_Object *obj, void *event_info);
+void test_scaling2(void *data, Evas_Object *obj, void *event_info);
+void test_slider(void *data, Evas_Object *obj, void *event_info);
+void test_actionslider(void *data, Evas_Object *obj, void *event_info);
+void test_genlist(void *data, Evas_Object *obj, void *event_info);
+void test_genlist2(void *data, Evas_Object *obj, void *event_info);
+void test_genlist3(void *data, Evas_Object *obj, void *event_info);
+void test_genlist4(void *data, Evas_Object *obj, void *event_info);
+void test_genlist5(void *data, Evas_Object *obj, void *event_info);
+void test_genlist6(void *data, Evas_Object *obj, void *event_info);
+void test_genlist7(void *data, Evas_Object *obj, void *event_info);
+void test_genlist8(void *data, Evas_Object *obj, void *event_info);
+void test_genlist9(void *data, Evas_Object *obj, void *event_info);
+void test_table(void *data, Evas_Object *obj, void *event_info);
+void test_gengrid(void *data, Evas_Object *obj, void *event_info);
+void test_gengrid2(void *data, Evas_Object *obj, void *event_info);
+void test_pager(void *data, Evas_Object *obj, void *event_info);
+void test_pager_slide(void *data, Evas_Object *obj, void *event_info);
+void test_win_state(void *data, Evas_Object *obj, void *event_info);
+void test_win_state2(void *data, Evas_Object *obj, void *event_info);
+void test_progressbar(void *data, Evas_Object *obj, void *event_info);
+void test_fileselector(void *data, Evas_Object *obj, void *event_info);
+void test_separator(void *data, Evas_Object *obj, void *event_info);
+void test_scroller(void *data, Evas_Object *obj, void *event_info);
+void test_scroller2(void *data, Evas_Object *obj, void *event_info);
+void test_spinner(void *data, Evas_Object *obj, void *event_info);
+void test_index(void *data, Evas_Object *obj, void *event_info);
+void test_index2(void *data, Evas_Object *obj, void *event_info);
+void test_photocam(void *data, Evas_Object *obj, void *event_info);
+void test_photo(void *data, Evas_Object *obj, void *event_info);
+void test_thumb(void *data, Evas_Object *obj, void *event_info);
+void test_icon_desktops(void *data, Evas_Object *obj, void *event_info);
+void test_notify(void *data, Evas_Object *obj, void *event_info);
+void test_slideshow(void *data, Evas_Object *obj, void *event_info);
+void test_menu(void *data, Evas_Object *obj, void *event_info);
+void test_panel(void *data, Evas_Object *obj, void *event_info);
+void test_panes(void *data, Evas_Object *obj, void *event_info);
+void test_calendar(void *data, Evas_Object *obj, void *event_info);
+void test_calendar2(void *data, Evas_Object *obj, void *event_info);
+void test_map(void *data, Evas_Object *obj, void *event_info);
+void test_weather(void *data, Evas_Object *obj, void *event_info);
+void test_flip(void *data, Evas_Object *obj, void *event_info);
+void test_flip2(void *data, Evas_Object *obj, void *event_info);
+void test_flip3(void *data, Evas_Object *obj, void *event_info);
+void test_label(void *data, Evas_Object *obj, void *event_info);
+void test_conformant(void *data, Evas_Object *obj, void *event_info);
+void test_conformant2(void *data, Evas_Object *obj, void *event_info);
+void test_multi(void *data, Evas_Object *obj, void *event_info);
+void test_floating(void *data, Evas_Object *obj, void *event_info);
+void test_launcher(void *data, Evas_Object *obj, void *event_info);
+void test_launcher2(void *data, Evas_Object *obj, void *event_info);
+void test_launcher3(void *data, Evas_Object *obj, void *event_info);
+void test_anim(void *data, Evas_Object *obj, void *event_info);
+void test_tooltip(void *data, Evas_Object *obj, void *event_info);
+void test_tooltip2(void *data, Evas_Object *obj, void *event_info);
+void test_cursor(void *data, Evas_Object *obj, void *event_info);
+void test_cursor2(void *data, Evas_Object *obj, void *event_info);
+void test_cursor3(void *data, Evas_Object *obj, void *event_info);
+void test_focus(void *data, Evas_Object *obj, void *event_info);
+void test_focus2(void *data, Evas_Object *obj, void *event_info);
+void test_flipselector(void *data, Evas_Object *obj, void *event_info);
+void test_diskselector(void *data, Evas_Object *obj, void *event_info);
+void test_colorselector(void *data, Evas_Object *obj, void *event_info);
+void test_ctxpopup(void *data, Evas_Object *obj, void *event_info);
+void test_bubble(void *data, Evas_Object *obj, void *event_info);
+void test_store(void *data, Evas_Object *obj, void *event_info);
+
+struct elm_test
+{
+   const char *name;
+   void (*cb)(void *, Evas_Object *, void *);
+};
+
+static int
+elm_test_sort(const void *pa, const void *pb)
+{
+   const struct elm_test *a = pa, *b = pb;
+   return strcasecmp(a->name, b->name);
+}
+
+static void
+elm_test_add(Eina_List **p_list, const char *name, void (*cb)(void *, Evas_Object *, void *))
+{
+   struct elm_test *t = malloc(sizeof(struct elm_test));
+   t->name = name;
+   t->cb = cb;
+   *p_list = eina_list_sorted_insert(*p_list, elm_test_sort, t);
+}
+
+static void
+my_win_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   /* called when my_win_main is requested to be deleted */
+   elm_exit(); /* exit the program's main loop that runs in elm_run() */
+}
+
+static void
+index_changed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   elm_list_item_show(event_info);
+}
+
+static void
+my_win_main(char *autorun)
+{
+   Evas_Object *win, *bg, *bx0, *lb, *li, *idx, *fr;
+   Eina_List *tests, *l;
+   struct elm_test *t;
+
+   /* 1 create an elm window - it returns an evas object. this is a little
+    * special as the object lives in the canvas that is inside the window
+    * so what is returned is really inside the window, but as you manipulate
+    * the evas object returned - the window will respond. elm_win makes sure
+    * of that so you can blindly treat it like any other evas object
+    * pretty much, just as long as you know it has special significance */
+   /* the first parameter is a "parent" window - eg for a dialog you want to
+    * have a main window it is related to, here it is NULL meaning there
+    * is no parent. "main" is the name of the window - used by the window
+    * manager for identifying the window uniquely amongst all the windows
+    * within this application (and all instances of the application). the
+    * type is a basic window (the final parameter) */
+   win = elm_win_add(NULL, "main", ELM_WIN_BASIC);
+   /* set the title of the window - this is in the titlebar */
+   elm_win_title_set(win, "Elementary Tests");
+
+   /* set a callback on the window when "delete,request" is emitted as
+    * a callback. when this happens my_win_del() is called and the
+    * data pointer (first param) is passed the final param here (in this
+    * case it is NULL). This is how you can pass specific things to a
+    * callback like objects or data layered on top */
+   evas_object_smart_callback_add(win, "delete,request", my_win_del, NULL);
+
+   /* add a background to our window. this just uses the standard theme set
+    * background. without a background, you could make a window seem
+    * transparent with elm_win_alpha_set(win, 1); for example. if you have
+    * a compositor running this will make the window able to be
+    * semi-transparent and any space not filled by object/widget pixels will
+    * be transparent or translucent based on alpha. if you do not have a
+    * comnpositor running this should fall back to using shaped windows
+    * (which have a mask). both these features will be slow and rely on
+    * a lot more resources, so only use it if you need it. */
+   bg = elm_bg_add(win);
+   /* set weight to 1.0 x 1.0 == expand in both x and y direction */
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   /* tell the window that this object is to be resized along with the window.
+    * also as a result this object will be one of several objects that
+    * controls the minimum/maximum size of the window */
+   elm_win_resize_object_add(win, bg);
+   /* and show the background */
+   evas_object_show(bg);
+
+   /* add a box layout widget to the window */
+   bx0 = elm_box_add(win);
+   /* allow base box (bx0) to expand in x and y */
+   evas_object_size_hint_weight_set(bx0, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   /* tell the window that the box affects window size and also will be
+    * resized when the window is */
+   elm_win_resize_object_add(win, bx0);
+   evas_object_show(bx0);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Information");
+   elm_box_pack_end(bx0, fr);
+   evas_object_show(fr);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "Please select a test from the list below<br>"
+                      "by clicking the test button to show the<br>"
+                      "test window.");
+   elm_frame_content_set(fr, lb);
+   evas_object_show(lb);
+
+   li = elm_list_add(win);
+   elm_list_always_select_mode_set(li, 1);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx0, li);
+   evas_object_show(li);
+
+   idx = elm_index_add(win);
+   evas_object_smart_callback_add(idx, "delay,changed", index_changed, NULL);
+   evas_object_size_hint_weight_set(idx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, idx);
+   evas_object_show(idx);
+
+   tests = NULL;
+#define ADD_TEST(name_, cb_) elm_test_add(&tests, name_, cb_)
+   ADD_TEST("Bg Plain", test_bg_plain);
+   ADD_TEST("Bg Image", test_bg_image);
+   ADD_TEST("Bg Options", test_bg_options);
+   ADD_TEST("Icon Transparent", test_icon);
+   ADD_TEST("Box Vert", test_box_vert);
+   ADD_TEST("Box Vert 2", test_box_vert2);
+   ADD_TEST("Box Horiz", test_box_horiz);
+   ADD_TEST("Box Transition", test_box_transition);
+   ADD_TEST("Buttons", test_button);
+   ADD_TEST("Transit", test_transit);
+   ADD_TEST("Transit 2", test_transit2);
+   ADD_TEST("Transit 3", test_transit3);
+   ADD_TEST("Transit 4", test_transit4);
+   ADD_TEST("Transit 5", test_transit5);
+   ADD_TEST("Transit 6", test_transit6);
+   ADD_TEST("Transit 7", test_transit7);
+   ADD_TEST("Transit 8", test_transit8);
+   ADD_TEST("File Selector Button", test_fileselector_button);
+   ADD_TEST("File Selector Entry", test_fileselector_entry);
+   ADD_TEST("Toggles", test_toggle);
+   ADD_TEST("Table", test_table);
+   ADD_TEST("Clock", test_clock);
+   ADD_TEST("Clock 2", test_clock2);
+   ADD_TEST("Layout", test_layout);
+   ADD_TEST("Hover", test_hover);
+   ADD_TEST("Hover 2", test_hover2);
+   ADD_TEST("Entry", test_entry);
+   ADD_TEST("Entry Scrolled", test_entry_scrolled);
+   ADD_TEST("Entry 3", test_entry3);
+   ADD_TEST("Entry 4", test_entry4);
+   ADD_TEST("Entry 5", test_entry5);
+   ADD_TEST("Entry Notepad", test_entry_notepad);
+   ADD_TEST("Anchorview", test_anchorview);
+   ADD_TEST("Anchorblock", test_anchorblock);
+   ADD_TEST("Toolbar", test_toolbar);
+   ADD_TEST("Toolbar 2", test_toolbar2);
+   ADD_TEST("Toolbar 3", test_toolbar3);
+   ADD_TEST("Toolbar 4", test_toolbar4);
+   ADD_TEST("Toolbar 5", test_toolbar5);
+   ADD_TEST("Hoversel", test_hoversel);
+   ADD_TEST("List", test_list);
+   ADD_TEST("List - Horizontal", test_list_horizontal);
+   ADD_TEST("List 2", test_list2);
+   ADD_TEST("List 3", test_list3);
+   ADD_TEST("List 4", test_list4);
+   ADD_TEST("List 5", test_list5);
+   ADD_TEST("Inwin", test_inwin);
+   ADD_TEST("Inwin 2", test_inwin2);
+   ADD_TEST("Scaling", test_scaling);
+   ADD_TEST("Scaling 2", test_scaling2);
+   ADD_TEST("Slider", test_slider);
+   ADD_TEST("Actionslider", test_actionslider);
+   ADD_TEST("Genlist", test_genlist);
+   ADD_TEST("Genlist 2", test_genlist2);
+   ADD_TEST("Genlist 3", test_genlist3);
+   ADD_TEST("Genlist 4", test_genlist4);
+   ADD_TEST("Genlist 5", test_genlist5);
+   ADD_TEST("Genlist 7", test_genlist7);
+   ADD_TEST("Genlist Tree", test_genlist6);
+   ADD_TEST("Genlist Group", test_genlist8);
+   ADD_TEST("Genlist Group Tree", test_genlist9);
+   ADD_TEST("GenGrid", test_gengrid);
+   ADD_TEST("GenGrid 2", test_gengrid2);
+   ADD_TEST("Checks", test_check);
+   ADD_TEST("Radios", test_radio);
+   ADD_TEST("Pager", test_pager);
+   ADD_TEST("Pager Slide", test_pager_slide);
+   ADD_TEST("Window States", test_win_state);
+   ADD_TEST("Window States 2", test_win_state2);
+   ADD_TEST("Progressbar", test_progressbar);
+   ADD_TEST("File Selector", test_fileselector);
+   ADD_TEST("Separator", test_separator);
+   ADD_TEST("Scroller", test_scroller);
+   ADD_TEST("Scroller 2", test_scroller2);
+   ADD_TEST("Spinner", test_spinner);
+   ADD_TEST("Index", test_index);
+   ADD_TEST("Index 2", test_index2);
+   ADD_TEST("Photocam", test_photocam);
+   ADD_TEST("Photo", test_photo);
+   ADD_TEST("Thumb", test_thumb);
+   ADD_TEST("Icon Desktops", test_icon_desktops);
+   ADD_TEST("Notify", test_notify);
+   ADD_TEST("Slideshow", test_slideshow);
+   ADD_TEST("Menu", test_menu);
+   ADD_TEST("Panel", test_panel);
+   ADD_TEST("Panes", test_panes);
+   ADD_TEST("Map", test_map);
+   ADD_TEST("Weather", test_weather);
+   ADD_TEST("Flip", test_flip);
+   ADD_TEST("Flip 2", test_flip2);
+   ADD_TEST("Flip 3", test_flip3);
+   ADD_TEST("Label", test_label);
+   ADD_TEST("Conformant", test_conformant);
+   ADD_TEST("Conformant 2", test_conformant2);
+   ADD_TEST("Multi Touch", test_multi);
+   ADD_TEST("Floating Objects", test_floating);
+   ADD_TEST("Launcher", test_launcher);
+   ADD_TEST("Launcher 2", test_launcher2);
+   ADD_TEST("Launcher 3", test_launcher3);
+   ADD_TEST("Animation", test_anim);
+   ADD_TEST("Calendar", test_calendar);
+   ADD_TEST("Calendar 2", test_calendar2);
+   ADD_TEST("Tooltip", test_tooltip);
+   ADD_TEST("Tooltip2", test_tooltip2);
+   ADD_TEST("Cursor", test_cursor);
+   ADD_TEST("Cursor 2", test_cursor2);
+   ADD_TEST("Cursor 3", test_cursor3);
+   ADD_TEST("Focus", test_focus);
+   ADD_TEST("Focus 2", test_focus2);
+   ADD_TEST("Flip Selector", test_flipselector);
+   ADD_TEST("Disk Selector", test_diskselector);
+   ADD_TEST("Color Selector", test_colorselector);
+   ADD_TEST("Ctxpopup", test_ctxpopup);
+   ADD_TEST("Bubble", test_bubble);
+   ADD_TEST("Store", test_store);
+#undef ADD_TEST
+
+   if (autorun)
+     {
+        EINA_LIST_FOREACH(tests, l, t)
+          if ((t->name) && (t->cb) && (!strcmp(t->name, autorun)))
+            t->cb(NULL, NULL, NULL);
+     }
+
+   if (tests)
+     {
+       char last_letter = 0;
+       EINA_LIST_FREE(tests, t)
+         {
+            Elm_List_Item *it;
+            it = elm_list_item_append(li, t->name, NULL, NULL, t->cb, NULL);
+            if (last_letter != t->name[0])
+              {
+                 char letter[2] = {t->name[0], '\0'};
+                 elm_index_item_append(idx, letter, it);
+                 last_letter = t->name[0];
+              }
+            free(t);
+         }
+       elm_index_item_go(idx, 0);
+     }
+
+   elm_list_go(li);
+
+   /* set an initial window size */
+   evas_object_resize(win, 320, 480);
+   /* show the window */
+   evas_object_show(win);
+}
+
+/* this is your elementary main function - it MUSt be called IMMEDIATELY
+ * after elm_init() and MUSt be passed argc and argv, and MUST be called
+ * elm_main and not be static - must be a visible symbol with EAPI infront */
+EAPI int
+elm_main(int argc, char **argv)
+{
+   char *autorun = NULL;
+
+   /* if called with a single argument try to autorun a test with
+    * the same name as the given param
+    * ex:  elementary_test "Box Vert 2" */
+   if (argc == 2)
+     autorun = argv[1];
+
+   /* put here any init specific to this app like parsing args etc. */
+   my_win_main(autorun); /* create main window */
+   elm_run(); /* and run the program now  and handle all events etc. */
+   /* if the mainloop that elm_run() runs exist - we exit the app */
+   elm_shutdown(); /* clean up and shut down */
+   /* exit code */
+   return 0;
+}
+#endif
+/* all emeentary apps should use this. but it right after elm_main() */
+ELM_MAIN()
diff --git a/src/bin/test_actionslider.c b/src/bin/test_actionslider.c
new file mode 100644 (file)
index 0000000..973f532
--- /dev/null
@@ -0,0 +1,131 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void _pos_selected_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   printf("Selection: %s\n", (char *)event_info);
+   printf("Label selected: %s\n", elm_actionslider_selected_label_get(obj));
+}
+
+static void
+_position_change_magnetic_cb(void *data __UNUSED__, Evas_Object * obj, void *event_info)
+{
+   if (!strcmp((char *)event_info, "left"))
+     elm_actionslider_magnet_pos_set(obj, ELM_ACTIONSLIDER_LEFT);
+   else if (!strcmp((char *)event_info, "right"))
+     elm_actionslider_magnet_pos_set(obj, ELM_ACTIONSLIDER_RIGHT);
+}
+
+static void
+_magnet_enable_disable_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   if (!strcmp((char *)event_info, "left"))
+      elm_actionslider_magnet_pos_set(obj, ELM_ACTIONSLIDER_CENTER);
+   else if (!strcmp((char *)event_info, "right"))
+      elm_actionslider_magnet_pos_set(obj, ELM_ACTIONSLIDER_NONE);
+}
+
+void
+test_actionslider(void *data __UNUSED__, Evas_Object * obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ms;
+
+   win = elm_win_add(NULL, "actionslider", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Actionslider");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, 0);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ms = elm_actionslider_add(win);
+   evas_object_size_hint_weight_set(ms, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(ms, EVAS_HINT_FILL, 0);
+   elm_actionslider_indicator_pos_set(ms, ELM_ACTIONSLIDER_RIGHT);
+   elm_actionslider_magnet_pos_set(ms, ELM_ACTIONSLIDER_RIGHT);
+   elm_actionslider_labels_set(ms, "Snooze", NULL, "Stop");
+   elm_actionslider_enabled_pos_set(ms, ELM_ACTIONSLIDER_LEFT |
+                                    ELM_ACTIONSLIDER_RIGHT);
+   evas_object_smart_callback_add(ms, "pos_changed",
+                                  _position_change_magnetic_cb, NULL);
+   evas_object_smart_callback_add(ms, "selected", _pos_selected_cb, NULL);
+   evas_object_show(ms);
+   elm_box_pack_end(bx, ms);
+
+   ms = elm_actionslider_add(win);
+   evas_object_size_hint_weight_set(ms, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(ms, EVAS_HINT_FILL, 0);
+   elm_actionslider_indicator_pos_set(ms, ELM_ACTIONSLIDER_CENTER);
+   elm_actionslider_magnet_pos_set(ms, ELM_ACTIONSLIDER_CENTER);
+   elm_actionslider_labels_set(ms, "Snooze", NULL, "Stop");
+   elm_actionslider_enabled_pos_set(ms, ELM_ACTIONSLIDER_LEFT |
+                                    ELM_ACTIONSLIDER_RIGHT);
+   evas_object_smart_callback_add(ms, "selected", _pos_selected_cb, NULL);
+   evas_object_show(ms);
+   elm_box_pack_end(bx, ms);
+
+   ms = elm_actionslider_add(win);
+   elm_object_style_set(ms, "bar");
+   evas_object_size_hint_weight_set(ms, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(ms, EVAS_HINT_FILL, 0);
+   elm_actionslider_indicator_pos_set(ms, ELM_ACTIONSLIDER_LEFT);
+   elm_actionslider_magnet_pos_set(ms, ELM_ACTIONSLIDER_CENTER|
+                                   ELM_ACTIONSLIDER_RIGHT);
+   elm_actionslider_enabled_pos_set(ms, ELM_ACTIONSLIDER_CENTER |
+                                    ELM_ACTIONSLIDER_RIGHT);
+   elm_actionslider_labels_set(ms, NULL, "Accept", "Reject");
+   evas_object_smart_callback_add(ms, "selected", _pos_selected_cb, NULL);
+   evas_object_show(ms);
+   elm_box_pack_end(bx, ms);
+
+   ms = elm_actionslider_add(win);
+   elm_object_style_set(ms, "bar");
+   evas_object_size_hint_weight_set(ms, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(ms, EVAS_HINT_FILL, 0);
+   elm_actionslider_indicator_pos_set(ms, ELM_ACTIONSLIDER_LEFT);
+   elm_actionslider_magnet_pos_set(ms, ELM_ACTIONSLIDER_LEFT);
+   elm_actionslider_labels_set(ms, NULL, "Accept", "Reject");
+   elm_actionslider_indicator_label_set(ms, "Go");
+   evas_object_smart_callback_add(ms, "pos_changed",
+                                  _position_change_magnetic_cb, NULL);
+   evas_object_smart_callback_add(ms, "selected", _pos_selected_cb, NULL);
+   evas_object_show(ms);
+   elm_box_pack_end(bx, ms);
+
+
+   ms = elm_actionslider_add(win);
+   evas_object_size_hint_weight_set(ms, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(ms, EVAS_HINT_FILL, 0);
+   elm_actionslider_indicator_pos_set(ms, ELM_ACTIONSLIDER_LEFT);
+   elm_actionslider_magnet_pos_set(ms, ELM_ACTIONSLIDER_ALL);
+   elm_actionslider_labels_set(ms, "Left", "Center", "Right");
+   elm_actionslider_indicator_label_set(ms, "Go");
+   evas_object_smart_callback_add(ms, "selected", _pos_selected_cb, NULL);
+   evas_object_show(ms);
+   elm_box_pack_end(bx, ms);
+
+   ms = elm_actionslider_add(win);
+   evas_object_size_hint_weight_set(ms, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(ms, EVAS_HINT_FILL, 0);
+   elm_actionslider_indicator_pos_set(ms, ELM_ACTIONSLIDER_CENTER);
+   elm_actionslider_magnet_pos_set(ms, ELM_ACTIONSLIDER_CENTER);
+   elm_actionslider_labels_set(ms, "Enable", "Magnet", "Disable");
+   evas_object_smart_callback_add(ms, "pos_changed",
+                                  _magnet_enable_disable_cb, NULL);
+   evas_object_smart_callback_add(ms, "selected", _pos_selected_cb, NULL);
+   evas_object_show(ms);
+   elm_box_pack_end(bx, ms);
+
+   evas_object_resize(win, 320, 400);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_anchorblock.c b/src/bin/test_anchorblock.c
new file mode 100644 (file)
index 0000000..89c7f83
--- /dev/null
@@ -0,0 +1,243 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+_print_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("bubble clicked\n");
+}
+
+static void
+my_anchorblock_bt(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *av = data;
+   elm_anchorblock_hover_end(av);
+}
+
+static void
+my_anchorblock_anchor(void *data, Evas_Object *obj, void *event_info)
+{
+   Evas_Object *av = data;
+   Elm_Entry_Anchorblock_Info *ei = event_info;
+   Evas_Object *bt, *bx;
+
+   bt = elm_button_add(obj);
+   elm_button_label_set(bt, ei->name);
+   elm_hover_content_set(ei->hover, "middle", bt);
+   evas_object_show(bt);
+
+   // hints as to where we probably should put hover contents (buttons etc.).
+   if (ei->hover_top)
+     {
+       bx = elm_box_add(obj);
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Top 1");
+       elm_box_pack_end(bx, bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorblock_bt, av);
+       evas_object_show(bt);
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Top 2");
+       elm_box_pack_end(bx, bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorblock_bt, av);
+       evas_object_show(bt);
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Top 3");
+       elm_box_pack_end(bx, bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorblock_bt, av);
+       evas_object_show(bt);
+       elm_hover_content_set(ei->hover, "top", bx);
+       evas_object_show(bx);
+     }
+   if (ei->hover_bottom)
+     {
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Bot");
+       elm_hover_content_set(ei->hover, "bottom", bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorblock_bt, av);
+       evas_object_show(bt);
+     }
+   if (ei->hover_left)
+     {
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Left");
+       elm_hover_content_set(ei->hover, "left", bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorblock_bt, av);
+       evas_object_show(bt);
+     }
+   if (ei->hover_right)
+     {
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Right");
+       elm_hover_content_set(ei->hover, "right", bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorblock_bt, av);
+       evas_object_show(bt);
+     }
+}
+
+static void
+my_anchorblock_edge_left(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("left\n");
+}
+
+static void
+my_anchorblock_edge_right(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("right\n");
+}
+
+static void
+my_anchorblock_edge_top(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("top\n");
+}
+
+static void
+my_anchorblock_edge_bottom(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("bottom\n");
+}
+
+static void
+my_anchorblock_scroll(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Coord x, y, w, h, vw, vh;
+
+   elm_scroller_region_get(obj, &x, &y, &w, &h);
+   elm_scroller_child_size_get(obj, &vw, &vh);
+   printf("scroll %ix%i +%i+%i in %ix%i\n", w, h, x, y, vw, vh);
+}
+
+void
+test_anchorblock(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *av, *sc, *bx, *bb, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "anchorblock", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Anchorblock");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, sc);
+
+   evas_object_smart_callback_add(sc, "edge_left", my_anchorblock_edge_left, NULL);
+   evas_object_smart_callback_add(sc, "edge_right", my_anchorblock_edge_right, NULL);
+   evas_object_smart_callback_add(sc, "edge_top", my_anchorblock_edge_top, NULL);
+   evas_object_smart_callback_add(sc, "edge_bottom", my_anchorblock_edge_bottom, NULL);
+   evas_object_smart_callback_add(sc, "scroll", my_anchorblock_scroll, NULL);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1);
+
+   bb = elm_bubble_add(win);
+   elm_bubble_label_set(bb, "Message 3");
+   elm_bubble_info_set(bb, "10:32 4/11/2008");
+   elm_bubble_icon_set(bb, ic);
+   evas_object_smart_callback_add(bb, "clicked", _print_clicked, NULL);
+   evas_object_show(ic);
+   evas_object_size_hint_weight_set(bb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   av = elm_anchorblock_add(win);
+   elm_anchorblock_hover_style_set(av, "popout");
+   elm_anchorblock_hover_parent_set(av, win);
+   elm_anchorblock_text_set(av,
+                          "Hi there. This is the most recent message in the "
+                          "list of messages. It has one <a href=tel:+614321234>+61 432 1234</a> "
+                          "(phone number) to click on.");
+   evas_object_smart_callback_add(av, "anchor,clicked", 
+                                  my_anchorblock_anchor, av);
+   elm_bubble_content_set(bb, av);
+   evas_object_show(av);
+   elm_box_pack_end(bx, bb);
+   evas_object_show(bb);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   bb = elm_bubble_add(win);
+   elm_bubble_label_set(bb, "Message 2");
+   elm_bubble_info_set(bb, "7:16 27/10/2008");
+   elm_bubble_icon_set(bb, ic);
+   evas_object_smart_callback_add(bb, "clicked", _print_clicked, NULL);
+   evas_object_show(ic);
+   evas_object_size_hint_weight_set(bb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   av = elm_anchorblock_add(win);
+   elm_anchorblock_hover_style_set(av, "popout");
+   elm_anchorblock_hover_parent_set(av, win);
+   elm_anchorblock_text_set(av,
+                          "Hey what are you doing? This is the second last message "
+                          "Hi there. This is the most recent message in the "
+                          "list. It's a longer one so it can wrap more and "
+                          "contains a <a href=contact:john>John</a> contact "
+                          "link in it to test popups on links. The idea is that "
+                          "all SMS's are scanned for things that look like phone "
+                          "numbers or names that are in your contacts list, and "
+                          "if they are, they become clickable links that pop up "
+                          "a menus of obvious actions to perform on this piece "
+                          "of information. This of course can be later explicitly "
+                          "done by links maybe running local apps or even being "
+                          "web URL's too that launch the web browser and point it "
+                          "to that URL. <item relsize=16x16 vsize=full href=emoticon/omg></item>");
+   evas_object_smart_callback_add(av, "anchor,clicked", my_anchorblock_anchor, av);
+   elm_bubble_content_set(bb, av);
+   evas_object_show(av);
+   elm_box_pack_end(bx, bb);
+   evas_object_show(bb);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1);
+
+   bb = elm_bubble_add(win);
+   elm_bubble_label_set(bb, "Message 1");
+   elm_bubble_info_set(bb, "20:47 18/6/2008");
+   elm_bubble_icon_set(bb, ic);
+   evas_object_smart_callback_add(bb, "clicked", _print_clicked, NULL);
+   evas_object_show(ic);
+   evas_object_size_hint_weight_set(bb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   av = elm_anchorblock_add(win);
+   elm_anchorblock_hover_style_set(av, "popout");
+   elm_anchorblock_hover_parent_set(av, win);
+   elm_anchorblock_text_set(av, "This is a short message. <item relsize=16x16 vsize=full href=emoticon/haha></item>");
+   evas_object_smart_callback_add(av, "anchor,clicked", 
+                                  my_anchorblock_anchor, av);
+   elm_bubble_content_set(bb, av);
+   evas_object_show(av);
+   elm_box_pack_end(bx, bb);
+   evas_object_show(bb);
+
+   elm_scroller_content_set(sc, bx);
+   evas_object_show(bx);
+   
+   evas_object_show(sc);
+
+   evas_object_resize(win, 320, 300);
+
+   elm_object_focus(win);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_anchorview.c b/src/bin/test_anchorview.c
new file mode 100644 (file)
index 0000000..9d79664
--- /dev/null
@@ -0,0 +1,108 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+my_anchorview_bt(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *av = data;
+   elm_anchorview_hover_end(av);
+}
+
+static void
+my_anchorview_anchor(void *data, Evas_Object *obj, void *event_info)
+{
+   Evas_Object *av = data;
+   Elm_Entry_Anchorview_Info *ei = event_info;
+   Evas_Object *bt, *bx;
+
+   bt = elm_button_add(obj);
+   elm_button_label_set(bt, ei->name);
+   elm_hover_content_set(ei->hover, "middle", bt);
+   evas_object_show(bt);
+
+   // hints as to where we probably should put hover contents (buttons etc.).
+   if (ei->hover_top)
+     {
+       bx = elm_box_add(obj);
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Top 1");
+       elm_box_pack_end(bx, bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorview_bt, av);
+       evas_object_show(bt);
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Top 2");
+       elm_box_pack_end(bx, bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorview_bt, av);
+       evas_object_show(bt);
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Top 3");
+       elm_box_pack_end(bx, bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorview_bt, av);
+       evas_object_show(bt);
+       elm_hover_content_set(ei->hover, "top", bx);
+       evas_object_show(bx);
+     }
+   if (ei->hover_bottom)
+     {
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Bot");
+       elm_hover_content_set(ei->hover, "bottom", bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorview_bt, av);
+       evas_object_show(bt);
+     }
+   if (ei->hover_left)
+     {
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Left");
+       elm_hover_content_set(ei->hover, "left", bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorview_bt, av);
+       evas_object_show(bt);
+     }
+   if (ei->hover_right)
+     {
+       bt = elm_button_add(obj);
+       elm_button_label_set(bt, "Right");
+       elm_hover_content_set(ei->hover, "right", bt);
+       evas_object_smart_callback_add(bt, "clicked", my_anchorview_bt, av);
+       evas_object_show(bt);
+     }
+}
+
+void
+test_anchorview(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *av;
+
+   win = elm_win_add(NULL, "anchorview", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Anchorview");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   av = elm_anchorview_add(win);
+   elm_anchorview_hover_style_set(av, "popout");
+   elm_anchorview_hover_parent_set(av, win);
+   elm_anchorview_text_set(av,
+                      "This is an entry widget in this window that<br>"
+                      "uses markup <b>like this</> for styling and<br>"
+                      "formatting <em>like this</>, as well as<br>"
+                      "<a href=X><link>links in the text</></a>, so enter text<br>"
+                      "in here to edit it. By the way, links are<br>"
+                      "called <a href=anc-02>Anchors</a> so you will need<br>"
+                      "to refer to them this way. <item relsize=16x16 vsize=full href=emoticon/guilty-smile></item>");
+   evas_object_size_hint_weight_set(av, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_smart_callback_add(av, "anchor,clicked", my_anchorview_anchor, av);
+   elm_win_resize_object_add(win, av);
+   evas_object_show(av);
+
+   evas_object_resize(win, 320, 300);
+
+   elm_object_focus(win);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_anim.c b/src/bin/test_anim.c
new file mode 100644 (file)
index 0000000..2601ef4
--- /dev/null
@@ -0,0 +1,113 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static const char *names[] =
+{
+     "bub1", "sh1",
+     "bub2", "sh2",
+     "bub3", "sh3",
+};
+
+static void
+_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Ecore_Animator *ani = evas_object_data_get(win, "animator");
+   
+   ecore_animator_del(ani);
+}
+
+static Eina_Bool
+anim(void *data)
+{
+   Evas_Object *win = data;
+   Evas_Object *bub, *sh;
+   Evas_Coord x, y, w, h, vw, vh;
+   double t, xx, yy, zz, r, fac;
+   double lx, ly;
+   unsigned int i;
+   
+   evas_output_viewport_get(evas_object_evas_get(win), 0, 0, &vw, &vh);
+   r = 48;
+   t = ecore_loop_time_get();
+   fac = 2.0 / (double)((sizeof(names) / sizeof(char *) / 2));
+   evas_pointer_canvas_xy_get(evas_object_evas_get(win), &x, &y);
+   lx = x;
+   ly = y;
+   
+   for (i = 0; i < (sizeof(names) / sizeof(char *) / 2); i++)
+     {
+        bub = evas_object_data_get(win, names[i * 2]);
+        sh = evas_object_data_get(win, names[(i * 2) + 1]);
+        zz = (((2 + sin(t * 6 + (M_PI * (i * fac)))) / 3) * 64) * 2;
+        xx = (cos(t * 4 + (M_PI * (i * fac))) * r) * 2;
+        yy = (sin(t * 6 + (M_PI * (i * fac))) * r) * 2;
+        
+        w = zz;
+        h = zz;
+        x = (vw / 2) + xx - (w / 2);
+        y = (vh / 2) + yy - (h / 2);
+        
+        evas_object_move(bub, x, y);
+        evas_object_resize(bub, w, h);
+       
+        x = x - ((lx - (x + (w / 2))) / 4);
+        y = y - ((ly - (y + (h / 2))) / 4);
+        
+        evas_object_move(sh, x, y);
+        evas_object_resize(sh, w, h);
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+void
+test_anim(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bub, *sh;
+   Ecore_Animator *ani;
+   char buf[PATH_MAX];
+   unsigned int i;
+   
+   win = elm_win_add(NULL, "animation", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Animation");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/rock_01.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+   
+   snprintf(buf, sizeof(buf), "%s/images/bubble_sh.png", PACKAGE_DATA_DIR);
+   for (i = 0; i < (sizeof(names) / sizeof(char *) / 2); i++)
+     {
+        sh = evas_object_image_filled_add(evas_object_evas_get(win));
+        evas_object_image_file_set(sh, buf, NULL);
+        evas_object_resize(sh, 64, 64);
+        evas_object_show(sh);
+        evas_object_data_set(win, names[(i * 2) + 1], sh);
+     }
+   
+   snprintf(buf, sizeof(buf), "%s/images/bubble.png", PACKAGE_DATA_DIR);
+    for (i = 0; i < (sizeof(names) / sizeof(char *) / 2); i++)
+     {
+        bub = evas_object_image_filled_add(evas_object_evas_get(win));
+        evas_object_image_file_set(bub, buf, NULL);
+        evas_object_resize(bub, 64, 64);
+        evas_object_show(bub);
+        evas_object_data_set(win, names[(i * 2)], bub);
+     }
+   
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+   
+   ani = ecore_animator_add(anim, win);
+   evas_object_data_set(win, "animator", ani);
+   
+   evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _del, win);
+}
+#endif
diff --git a/src/bin/test_bg.c b/src/bin/test_bg.c
new file mode 100644 (file)
index 0000000..a30b870
--- /dev/null
@@ -0,0 +1,211 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void 
+_cb_radio_changed(void *data, Evas_Object *obj, void *event __UNUSED__) 
+{
+   Evas_Object *o_bg = data;
+
+   elm_bg_option_set(o_bg, elm_radio_value_get((Evas_Object *)obj));
+}
+
+static void 
+_cb_overlay_changed(void *data, Evas_Object *obj, void *event __UNUSED__) 
+{
+   Evas_Object *o_bg = data;
+
+   if (elm_check_state_get(obj)) 
+     {
+        Evas_Object *parent, *over;
+        char buff[PATH_MAX];
+
+        snprintf(buff, sizeof(buff), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+        parent = elm_object_parent_widget_get(o_bg);
+        over = edje_object_add(evas_object_evas_get(parent));
+        edje_object_file_set(over, buff, "bg_overlay");
+        elm_bg_overlay_set(o_bg, over);
+     }
+   else 
+     elm_bg_overlay_set(o_bg, NULL);
+}
+
+static void 
+_cb_color_changed(void *data, Evas_Object *obj, void *event __UNUSED__) 
+{
+   Evas_Object *o_bg = data;
+   double val = 0.0;
+
+   val = elm_spinner_value_get(obj);
+   if (val == 1.0)
+     elm_bg_color_set(o_bg, 255, 255, 255);
+   else if (val == 2.0) 
+     elm_bg_color_set(o_bg, 255, 0, 0);
+   else if (val == 3.0) 
+     elm_bg_color_set(o_bg, 0, 0, 255);
+   else if (val == 4.0) 
+     elm_bg_color_set(o_bg, 0, 255, 0);
+}
+
+void
+test_bg_plain(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg;
+
+   win = elm_win_add(NULL, "bg-plain", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Bg Plain");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   /* allow bg to expand in x & y */
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   /* set size hints. a minimum size for the bg. this should propagate back
+    * to the window thus limiting its size based off the bg as the bg is one
+    * of the window's resize objects. */
+   evas_object_size_hint_min_set(bg, 160, 160);
+   /* and set a maximum size. not needed very often. normally used together
+    * with evas_object_size_hint_min_set() at the same size to make a
+    * window not resizable */
+   evas_object_size_hint_max_set(bg, 640, 640);
+   /* and now just resize the window to a size you want. normally widgets
+    * will determine the initial size though */
+   evas_object_resize(win, 320, 320);
+   /* and show the window */
+   evas_object_show(win);
+}
+
+void
+test_bg_image(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "bg-image", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Bg Image");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   evas_object_size_hint_min_set(bg, 160, 160);
+   evas_object_size_hint_max_set(bg, 640, 640);
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+void
+test_bg_options(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg;
+   Evas_Object *box, *hbox, *o_bg;
+   Evas_Object *rd, *rdg;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "bg-options", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Bg Options");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   box = elm_box_add(win);
+   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, box);
+   evas_object_show(box);
+
+   o_bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(o_bg, buf, NULL);
+   evas_object_size_hint_weight_set(o_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(o_bg, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(box, o_bg);
+   evas_object_show(o_bg);
+
+   hbox = elm_box_add(win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
+   evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, ELM_BG_OPTION_CENTER);
+   elm_radio_label_set(rd, "Center");
+   evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(rd, "changed", _cb_radio_changed, o_bg);
+   elm_box_pack_end(hbox, rd);
+   evas_object_show(rd);
+   rdg = rd;
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, ELM_BG_OPTION_SCALE);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_label_set(rd, "Scale");
+   evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(rd, "changed", _cb_radio_changed, o_bg);
+   elm_box_pack_end(hbox, rd);
+   evas_object_show(rd);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, ELM_BG_OPTION_STRETCH);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_label_set(rd, "Stretch");
+   evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(rd, "changed", _cb_radio_changed, o_bg);
+   elm_box_pack_end(hbox, rd);
+   evas_object_show(rd);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, ELM_BG_OPTION_TILE);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_label_set(rd, "Tile");
+   evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(rd, "changed", _cb_radio_changed, o_bg);
+   elm_box_pack_end(hbox, rd);
+   evas_object_show(rd);
+
+   elm_radio_value_set(rdg, ELM_BG_OPTION_SCALE);
+
+   rd = elm_check_add(win);
+   elm_check_label_set(rd, "Show Overlay");
+   evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(rd, "changed", _cb_overlay_changed, o_bg);
+   elm_box_pack_end(hbox, rd);
+   evas_object_show(rd);
+
+   /* color choices ... this is ghetto, but we don't have a 'colorpicker' 
+    * widget yet :( */
+   rd = elm_spinner_add(win);
+   elm_object_style_set(rd, "vertical");
+   elm_spinner_min_max_set(rd, 1, 4);
+   elm_spinner_label_format_set(rd, "%.0f");
+   elm_spinner_editable_set(rd, EINA_FALSE);
+   elm_spinner_special_value_add(rd, 1, "White");
+   elm_spinner_special_value_add(rd, 2, "Red");
+   elm_spinner_special_value_add(rd, 3, "Blue");
+   elm_spinner_special_value_add(rd, 4, "Green");
+   evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(rd, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(rd, "changed", _cb_color_changed, o_bg);
+   elm_box_pack_end(hbox, rd);
+   evas_object_show(rd);
+
+   elm_box_pack_end(box, hbox);
+   evas_object_show(hbox);
+
+   evas_object_size_hint_min_set(bg, 160, 160);
+   evas_object_size_hint_max_set(bg, 640, 640);
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_box.c b/src/bin/test_box.c
new file mode 100644 (file)
index 0000000..abdbfd4
--- /dev/null
@@ -0,0 +1,280 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_box_vert(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "box-vert", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Box Vert");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.5);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.0, 0.5);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, EVAS_HINT_EXPAND, 0.5);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   evas_object_show(win);
+}
+
+static void
+_del_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   elm_box_unpack(data, obj);
+   evas_object_move(obj, 0, 0);
+   evas_object_color_set(obj, 128, 64, 0, 128);
+//   evas_object_del(obj);
+}
+
+void
+test_box_vert2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt;
+
+   win = elm_win_add(NULL, "box-vert2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Box Vert 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, 0.0, 0.0);
+   evas_object_show(bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 1");
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 2");
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 3");
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 4");
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 5");
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   evas_object_show(win);
+}
+
+void
+test_box_horiz(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "box-horiz", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Box Horiz");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_box_horizontal_set(bx, 1);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.5);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.0);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.0, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   evas_object_show(win);
+}
+
+typedef struct
+{
+   Eina_List *transitions;
+   Evas_Object *box;
+   Evas_Object_Box_Layout last_layout;
+} Transitions_Data;
+
+static void
+_test_box_transition_change(void *data)
+{
+   Transitions_Data *tdata = data;
+   Elm_Box_Transition *layout_data;
+   Evas_Object_Box_Layout next_layout;
+
+   if (!data) return;
+   next_layout = eina_list_data_get(tdata->transitions);
+   layout_data = elm_box_transition_new(2.0, tdata->last_layout,
+         NULL, NULL, next_layout, NULL, NULL,
+         _test_box_transition_change, tdata);
+   elm_box_layout_set(tdata->box, elm_box_layout_transition, layout_data, elm_box_transition_free);
+   tdata->last_layout = next_layout;
+
+   tdata->transitions = eina_list_demote_list(tdata->transitions, tdata->transitions);
+}
+
+static void
+_win_del(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Transitions_Data *tdata = data;
+   elm_box_layout_set(tdata->box, evas_object_box_layout_horizontal, NULL, NULL);
+   free(data);
+}
+
+void
+test_box_transition(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt;
+   Transitions_Data *tdata;
+
+   win = elm_win_add(NULL, "box-transition", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Box Transition");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, 1.0, 1.0);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, 1.0, 1.0);
+
+   evas_object_show(bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 1");
+   evas_object_size_hint_weight_set(bt, 1.0, 1.0);
+   evas_object_size_hint_align_set(bt, -1.0, -1.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_resize(bt, 100, 100);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 2");
+   evas_object_size_hint_weight_set(bt, 1.0, 1.0);
+   evas_object_size_hint_align_set(bt, -1.0, -1.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_resize(bt, 100, 100);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 3");
+   evas_object_size_hint_weight_set(bt, 1.0, 1.0);
+   evas_object_size_hint_align_set(bt, -1.0, -1.0);
+   evas_object_smart_callback_add(bt, "clicked", _del_cb, bx);
+   elm_box_pack_end(bx, bt);
+   evas_object_resize(bt, 100, 100);
+   evas_object_show(bt);
+
+   tdata = calloc(1, sizeof(Transitions_Data));
+   tdata->box = bx;
+   tdata->last_layout = evas_object_box_layout_horizontal;
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_vertical);
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_horizontal);
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_stack);
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_homogeneous_vertical);
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_homogeneous_horizontal);
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_flow_vertical);
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_flow_horizontal);
+   tdata->transitions = eina_list_append(tdata->transitions,
+         evas_object_box_layout_stack);
+
+   evas_object_resize(win, 300, 300);
+   evas_object_resize(bx, 300, 300);
+   evas_object_smart_callback_add(win, "delete,request", _win_del, tdata);
+   evas_object_show(win);
+   elm_box_layout_set(bx, evas_object_box_layout_horizontal, NULL, NULL);
+   _test_box_transition_change(tdata);
+}
+#endif
diff --git a/src/bin/test_bubble.c b/src/bin/test_bubble.c
new file mode 100644 (file)
index 0000000..f8f7904
--- /dev/null
@@ -0,0 +1,81 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+_print_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("bubble clicked\n");
+}
+
+void
+test_bubble(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ic, *bb, *ct;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "box-vert", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Bubble");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1);
+
+   bb = elm_bubble_add(win);
+   elm_bubble_label_set(bb, "Message 1");
+   elm_bubble_info_set(bb, "Corner: bottom_right");
+   elm_bubble_icon_set(bb, ic);
+   elm_bubble_corner_set(bb, "bottom_right");
+   evas_object_smart_callback_add(bb, "clicked", _print_clicked, NULL);
+   evas_object_show(ic);
+   evas_object_size_hint_weight_set(bb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ct = elm_label_add(win);
+   elm_label_label_set(ct,
+                       "\"The future of the art: R or G or B?\",  by Rusty");
+   elm_bubble_content_set(bb, ct);
+
+   elm_box_pack_end(bx, bb);
+   evas_object_show(bb);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1);
+
+   bb = elm_bubble_add(win);
+   elm_bubble_label_set(bb, "Message 2");
+   elm_bubble_info_set(bb, "10:32 4/11/2008");
+   elm_bubble_icon_set(bb, ic);
+   evas_object_smart_callback_add(bb, "clicked", _print_clicked, NULL);
+   evas_object_show(ic);
+   evas_object_size_hint_weight_set(bb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ct = elm_label_add(win);
+   elm_label_label_set(ct, "Corner: base (top-left)");
+   elm_bubble_content_set(bb, ct);
+
+   elm_box_pack_end(bx, bb);
+   evas_object_show(bb);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_button.c b/src/bin/test_button.c
new file mode 100644 (file)
index 0000000..caf9a05
--- /dev/null
@@ -0,0 +1,174 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+_bt_repeated(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   static int count;
+   char buf[16];
+
+   snprintf(buf, sizeof(buf), "count=%d", count++);
+   if (count >= 10000)
+     count = 0;
+   elm_button_label_set(obj, buf);
+}
+
+static void
+_bt_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   int param = (int)(data);
+
+   printf("clicked event on Button:%d\n", param);
+}
+
+static void
+_bt_unpressed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   int param = (int)(data);
+
+   printf("unpressed event on Button:%d\n", param);
+}
+
+void
+test_button(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *scr, *bx, *ic, *bt;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "buttons", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Buttons");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   scr = elm_scroller_add(win);
+   elm_scroller_bounce_set(scr, EINA_FALSE, EINA_TRUE);
+   elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
+   elm_win_resize_object_add(win, scr);
+   evas_object_show(scr);
+   evas_object_size_hint_weight_set(scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_scroller_content_set(scr, bx);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Icon sized to button");
+   elm_button_icon_set(bt, ic);
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)1);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)1);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(bx);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Icon no scale");
+   elm_button_icon_set(bt, ic);
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)2);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)2);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Disabled Button");
+   elm_button_icon_set(bt, ic);
+   elm_object_disabled_set(bt, 1);
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)3);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)3);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+   
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   bt = elm_button_add(win);
+   elm_button_icon_set(bt, ic);
+   elm_object_disabled_set(bt, 1);
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)4);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)4);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Label Only");
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)5);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)5);
+   elm_box_pack_end(bx, bt);
+   evas_object_smart_callback_add(bt, "repeated", _bt_repeated, NULL);
+   elm_button_autorepeat_set(bt, 1);
+   elm_button_autorepeat_initial_timeout_set(bt, 2.0);
+   elm_button_autorepeat_gap_timeout_set(bt, 0.5);
+   evas_object_show(bt);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   bt = elm_button_add(win);
+   elm_button_icon_set(bt, ic);
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)6);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)6);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+
+   bt = elm_button_add(win);
+   elm_object_style_set(bt, "anchor");
+   elm_button_label_set(bt, "Anchor style");
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)7);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)7);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   bt = elm_button_add(win);
+   elm_object_style_set(bt, "anchor");
+   elm_button_icon_set(bt, ic);
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)8);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)8);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   bt = elm_button_add(win);
+   elm_object_style_set(bt, "anchor");
+   elm_button_icon_set(bt, ic);
+   elm_object_disabled_set(bt, 1);
+   evas_object_smart_callback_add(bt, "clicked", _bt_clicked, (void *)9);
+   evas_object_smart_callback_add(bt, "unpressed", _bt_unpressed, (void *)9);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_calendar.c b/src/bin/test_calendar.c
new file mode 100644 (file)
index 0000000..9259692
--- /dev/null
@@ -0,0 +1,181 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+/* A simple test, just displaying calendar in it's default state */
+void
+test_calendar(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *cal;
+
+   win = elm_win_add(NULL, "calendar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Calendar");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   cal = elm_calendar_add(win);
+   elm_win_resize_object_add(win, cal);
+   evas_object_size_hint_weight_set(cal, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(cal);
+
+   evas_object_show(win);
+}
+
+void
+_print_cal_info(Evas_Object *cal, Evas_Object *en)
+{
+   char info[1024];
+   double interval;
+   int year_min, year_max;
+   Eina_Bool sel_enabled;
+   const char **wds;
+   struct tm stime;
+
+   if (!elm_calendar_selected_time_get(cal, &stime))
+     return;
+
+   interval = elm_calendar_interval_get(cal);
+   elm_calendar_min_max_year_get(cal, &year_min, &year_max);
+   sel_enabled = elm_calendar_day_selection_enabled_get(cal);
+   wds = elm_calendar_weekdays_names_get(cal);
+
+   snprintf(info, sizeof(info),
+        "  Day: %i, Mon: %i, Year %i, WeekDay: %i<br>"
+        "  Interval: %0.2f, Year_Min: %i, Year_Max %i, Sel Enabled : %i<br>"
+        "  Weekdays: %s, %s, %s, %s, %s, %s, %s<br>",
+        stime.tm_mday, stime.tm_mon, stime.tm_year + 1900, stime.tm_wday,
+        interval, year_min, year_max, sel_enabled,
+        wds[0], wds[1], wds[2], wds[3], wds[4], wds[5], wds[6]);
+
+   elm_entry_entry_set(en, info);
+}
+
+static void
+_print_cal_info_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   _print_cal_info(obj, data);
+}
+
+static char *
+_format_month_year(struct tm *stime)
+{
+   char buf[32];
+   if (!strftime(buf, sizeof(buf), "%b %y", stime)) return NULL;
+   return strdup(buf);
+}
+
+/* A test intended to cover all the calendar api and much use cases as
+   possible */
+void
+test_calendar2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bxh, *cal, *cal2, *cal3, *en;
+   Elm_Calendar_Mark *mark;
+   struct tm selected_time;
+   time_t current_time;
+   const char *weekdays[] =
+   {
+      "Sunday", "Monday", "Tuesday", "Wednesday",
+      "Thursday", "Friday", "Saturday"
+   };
+
+   win = elm_win_add(NULL, "calendar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Calendar 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   bxh = elm_box_add(win);
+   elm_box_horizontal_set(bxh, EINA_TRUE);
+   evas_object_size_hint_weight_set(bxh, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bxh, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(bxh);
+   elm_box_pack_end(bx, bxh);
+
+   cal = elm_calendar_add(win);
+   evas_object_size_hint_weight_set(cal, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(cal, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(cal);
+   elm_box_pack_end(bx, cal);
+
+   cal2 = elm_calendar_add(win);
+   evas_object_size_hint_weight_set(cal2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(cal2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_calendar_day_selection_enabled_set(cal2, EINA_FALSE);
+   evas_object_show(cal2);
+   elm_box_pack_end(bxh, cal2);
+
+   cal3 = elm_calendar_add(win);
+   evas_object_size_hint_weight_set(cal3, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(cal3, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   current_time = time(NULL) + 34 * 84600;
+   localtime_r(&current_time, &selected_time);
+   elm_calendar_selected_time_set(cal3, &selected_time);
+   current_time = time(NULL) + 1 * 84600;
+   localtime_r(&current_time, &selected_time);
+   elm_calendar_mark_add(cal3, "checked", &selected_time, ELM_CALENDAR_UNIQUE);
+   elm_calendar_marks_clear(cal3);
+   current_time = time(NULL);
+   localtime_r(&current_time, &selected_time);
+   elm_calendar_mark_add(cal3, "checked", &selected_time, ELM_CALENDAR_DAILY);
+   elm_calendar_mark_add(cal3, "holiday", &selected_time, ELM_CALENDAR_DAILY);
+   elm_calendar_marks_draw(cal3);
+   evas_object_show(cal3);
+   elm_box_pack_end(bxh, cal3);
+
+   en = elm_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+   elm_entry_editable_set(en, EINA_FALSE);
+   evas_object_show(win);
+
+   elm_calendar_weekdays_names_set(cal, weekdays);
+   elm_calendar_interval_set(cal, 0.4);
+   elm_calendar_format_function_set(cal, _format_month_year);
+   elm_calendar_min_max_year_set(cal, 2010, 2020);
+
+   current_time = time(NULL) + 4 * 84600;
+   localtime_r(&current_time, &selected_time);
+   elm_calendar_mark_add(cal, "holiday", &selected_time, ELM_CALENDAR_ANNUALLY);
+
+   current_time = time(NULL) + 1 * 84600;
+   localtime_r(&current_time, &selected_time);
+   elm_calendar_mark_add(cal, "checked", &selected_time, ELM_CALENDAR_UNIQUE);
+
+   current_time = time(NULL) - 363 * 84600;
+   localtime_r(&current_time, &selected_time);
+   elm_calendar_mark_add(cal, "checked", &selected_time, ELM_CALENDAR_MONTHLY);
+
+   current_time = time(NULL) - 5 * 84600;
+   localtime_r(&current_time, &selected_time);
+   mark = elm_calendar_mark_add(cal, "holiday", &selected_time,
+        ELM_CALENDAR_WEEKLY);
+
+   current_time = time(NULL) + 1 * 84600;
+   localtime_r(&current_time, &selected_time);
+   elm_calendar_mark_add(cal, "holiday", &selected_time, ELM_CALENDAR_WEEKLY);
+
+   elm_calendar_mark_del(mark);
+   elm_calendar_marks_draw(cal);
+
+   _print_cal_info(cal, en);
+   evas_object_smart_callback_add(cal, "changed", _print_cal_info_cb, en);
+}
+
+#endif
diff --git a/src/bin/test_check.c b/src/bin/test_check.c
new file mode 100644 (file)
index 0000000..6d41324
--- /dev/null
@@ -0,0 +1,83 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_check(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ic, *ck;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "check", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Checks");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   ck = elm_check_add(win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, EVAS_HINT_FILL, 0.5);
+   elm_check_label_set(ck, "Icon sized to check");
+   elm_check_icon_set(ck, ic);
+   elm_check_state_set(ck, 1);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Icon no scale");
+   elm_check_icon_set(ck, ic);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+   evas_object_show(ic);
+
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Label Only");
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   ck = elm_check_add(win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, EVAS_HINT_FILL, 0.5);
+   elm_check_label_set(ck, "Disabled check");
+   elm_check_icon_set(ck, ic);
+   elm_check_state_set(ck, 1);
+   elm_box_pack_end(bx, ck);
+   elm_object_disabled_set(ck, 1);
+   evas_object_show(ck);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   ck = elm_check_add(win);
+   elm_check_icon_set(ck, ic);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+   evas_object_show(ic);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_clock.c b/src/bin/test_clock.c
new file mode 100644 (file)
index 0000000..b8b4a84
--- /dev/null
@@ -0,0 +1,146 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_clock(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ck;
+   unsigned int digedit;
+
+   win = elm_win_add(NULL, "clock", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Clock");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ck = elm_clock_add(win);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   ck = elm_clock_add(win);
+   elm_clock_show_am_pm_set(ck, 1);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   ck = elm_clock_add(win);
+   elm_clock_show_seconds_set(ck, 1);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   ck = elm_clock_add(win);
+   elm_clock_show_seconds_set(ck, 1);
+   elm_clock_show_am_pm_set(ck, 1);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   ck = elm_clock_add(win);
+   elm_clock_show_seconds_set(ck, 1);
+   elm_clock_show_am_pm_set(ck, 0);
+   elm_clock_time_set(ck, 23, 59, 57);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   ck = elm_clock_add(win);
+   elm_clock_edit_set(ck, 1);
+   elm_clock_show_seconds_set(ck, 1);
+   elm_clock_show_am_pm_set(ck, 1);
+   elm_clock_time_set(ck, 10, 11, 12);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   ck = elm_clock_add(win);
+   elm_clock_show_seconds_set(ck, 1);
+   elm_clock_edit_set(ck, 1);
+   digedit = ELM_CLOCK_HOUR_UNIT | ELM_CLOCK_MIN_UNIT | ELM_CLOCK_SEC_UNIT;
+   elm_clock_digit_edit_set(ck, digedit);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   evas_object_show(win);
+}
+
+static void
+_edit_bt_clicked(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *ck = data;
+
+   if (!elm_clock_edit_get(ck)) {
+       elm_button_label_set(obj, "Done");
+       elm_clock_edit_set(ck, 1);
+       return;
+   }
+   elm_button_label_set(obj, "Edit");
+   elm_clock_edit_set(ck, 0);
+}
+
+static void
+_hmode_bt_clicked(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *ck = data;
+
+   if (!elm_clock_show_am_pm_get(ck)) {
+       elm_button_label_set(obj, "24h");
+       elm_clock_show_am_pm_set(ck, 1);
+       return;
+   }
+   elm_button_label_set(obj, "12h");
+   elm_clock_show_am_pm_set(ck, 0);
+}
+
+void
+test_clock2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *hbx, *ck, *bt;
+
+   win = elm_win_add(NULL, "clock", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Clock 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ck = elm_clock_add(win);
+   elm_clock_show_seconds_set(ck, 1);
+   elm_clock_show_am_pm_set(ck, 1);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   hbx = elm_box_add(win);
+   evas_object_size_hint_weight_set(hbx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_horizontal_set(hbx, EINA_TRUE);
+   elm_box_pack_end(bx, hbx);
+   evas_object_show(hbx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Edit");
+   evas_object_smart_callback_add(bt, "clicked", _edit_bt_clicked, ck);
+   elm_box_pack_end(hbx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "24h");
+   evas_object_smart_callback_add(bt, "clicked", _hmode_bt_clicked, ck);
+   elm_box_pack_end(hbx, bt);
+   evas_object_show(bt);
+
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_colorselector.c b/src/bin/test_colorselector.c
new file mode 100644 (file)
index 0000000..0833703
--- /dev/null
@@ -0,0 +1,97 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+_colorselector_clicked_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *re = data;
+   int r, g, b, a;
+
+   elm_colorselector_color_get(obj, &r, &g, &b, &a);
+   printf("Current Color [r=%d g=%d b=%d a=%d]\n",r, g, b, a);
+
+   /* Fix Alpha pre multiplication by edje */
+   r = (r * a) / 255;
+   g = (g * a) / 255;
+   b = (b * a) / 255;
+
+   evas_object_color_set(re, r, g, b, a);
+}
+
+void
+test_colorselector(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *cp, *fr, *ly, *re;
+   char buf[PATH_MAX];
+   int r, g, b, a;
+
+   win = elm_win_add(NULL, "colorselector", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Color Selector");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_color_set(bg, 255, 255, 255, 255);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   fr = elm_frame_add(win);
+   evas_object_size_hint_weight_set(fr, 1.0, 0.5);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_label_set(fr, "Color View");
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   ly = elm_layout_add(win);
+   snprintf(buf, sizeof(buf), "%s/objects/colorpreview.edj", PACKAGE_DATA_DIR);
+   elm_layout_file_set(ly, buf, "main");
+   evas_object_size_hint_align_set(ly, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_frame_content_set(fr, ly);
+   evas_object_show(ly);
+
+   re = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_show(re);
+   elm_layout_content_set(ly, "ColorPreview", re);
+
+   fr = elm_frame_add(win);
+   evas_object_size_hint_weight_set(fr, 1.0, 0);
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, 0);
+   elm_frame_label_set(fr, "Color Selector");
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   cp = elm_colorselector_add(win);
+
+   a = 180;
+   r = 255;
+   g = 160;
+   b = 132;
+
+   elm_colorselector_color_set(cp, r, g, b, a);
+   evas_object_size_hint_weight_set(cp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(cp, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_frame_content_set(fr, cp);
+   evas_object_show(cp);
+   evas_object_smart_callback_add(cp, "changed", _colorselector_clicked_cb, re);
+
+   elm_colorselector_color_get(cp, &r, &g, &b, &a);
+   /* Fix Alpha pre multiplication by edje */
+   r = (r * a) / 255;
+   g = (g * a) / 255;
+   b = (b * a) / 255;
+   evas_object_color_set(re, r, g, b, a);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+
+}
+#endif
diff --git a/src/bin/test_conform.c b/src/bin/test_conform.c
new file mode 100644 (file)
index 0000000..9beafe8
--- /dev/null
@@ -0,0 +1,205 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+void 
+test_conformant(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__) 
+{
+   Evas_Object *win, *bg, *conform, *btn, *bx, *en;
+
+   win = elm_win_add(NULL, "conformant", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Conformant");
+   elm_win_autodel_set(win, 1);
+   elm_win_conformant_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   conform = elm_conformant_add(win);
+   elm_win_resize_object_add(win, conform);
+   evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(conform);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_scrolled_entry_bounce_set(en, 1, 0);
+   elm_scrolled_entry_entry_set(en, "This is the top entry here");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+  
+   btn = elm_button_add(win);
+   elm_button_label_set(btn, "Test Conformant");
+   evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, btn);
+   evas_object_show(btn);
+
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_scrolled_entry_bounce_set(en, 1, 0);
+   elm_scrolled_entry_entry_set(en, "This is the middle entry here");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+  
+   btn = elm_button_add(win);
+   elm_button_label_set(btn, "Test Conformant");
+   evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, btn);
+   evas_object_show(btn);
+
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_bounce_set(en, 0, 1);
+   elm_scrolled_entry_entry_set(en, 
+                       "This is a multi-line entry at the bottom<br>"
+                       "This can contain more than 1 line of text and be "
+                       "scrolled around to allow for entering of lots of "
+                       "content. It is also to test to see that autoscroll "
+                       "moves to the right part of a larger multi-line "
+                       "text entry that is inside of a scroller than can be "
+                       "scrolled around, thus changing the expected position "
+                       "as well as cursor changes updating auto-scroll when "
+                       "it is enabled.");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+  
+   elm_conformant_content_set(conform, bx);
+   evas_object_show(bx);
+   
+   evas_object_resize(win, 240, 240);
+   evas_object_show(win);
+}
+
+static void 
+popobj(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+  elm_pager_content_pop(data);
+}
+
+void 
+test_conformant2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__) 
+{
+   Evas_Object *win, *bg, *conform, *btn, *bx, *en, *pg;
+
+   win = elm_win_add(NULL, "conformant2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Conformant 2");
+   elm_win_autodel_set(win, 1);
+   elm_win_conformant_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_scrolled_entry_bounce_set(en, 1, 0);
+   elm_scrolled_entry_entry_set(en, "This is the top entry here");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, en);
+   evas_object_show(en);
+
+   btn = elm_button_add(win);
+   elm_object_focus_allow_set(btn, 0);
+   elm_button_label_set(btn, "Delete Below");
+   evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, btn);
+   evas_object_show(btn);
+  
+   pg = elm_pager_add(win);
+   evas_object_size_hint_weight_set(pg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(pg, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, pg);
+   evas_object_show(pg);
+  
+   evas_object_smart_callback_add(btn, "clicked", popobj, pg);
+  
+   conform = elm_conformant_add(win);
+   evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(conform, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_pager_content_push(pg, conform);
+   evas_object_show(conform);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_bounce_set(en, 0, 1);
+   elm_scrolled_entry_entry_set(en, "This entry and button below get deleted.");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+  
+   btn = elm_button_add(win);
+   elm_object_focus_allow_set(btn, 0);
+   elm_button_label_set(btn, "Delete this bottom bit 1");
+   evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, btn);
+   evas_object_show(btn);
+
+   evas_object_smart_callback_add(btn, "clicked", popobj, pg);
+  
+   elm_conformant_content_set(conform, bx);
+   evas_object_show(bx);
+   
+   conform = elm_conformant_add(win);
+   evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(conform, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_pager_content_push(pg, conform);
+   evas_object_show(conform);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_bounce_set(en, 0, 1);
+   elm_scrolled_entry_entry_set(en, "This entry and button below get deleted.");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+  
+   btn = elm_button_add(win);
+   elm_object_focus_allow_set(btn, 0);
+   elm_button_label_set(btn, "Delete this bottom bit 2");
+   evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, btn);
+   evas_object_show(btn);
+
+   evas_object_smart_callback_add(btn, "clicked", popobj, pg);
+  
+   elm_conformant_content_set(conform, bx);
+   evas_object_show(bx);
+   
+   evas_object_resize(win, 240, 480);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_ctxpopup.c b/src/bin/test_ctxpopup.c
new file mode 100644 (file)
index 0000000..1c4e0b8
--- /dev/null
@@ -0,0 +1,178 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+_ctxpopup_item_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("ctxpopup item selected: %s\n",
+          elm_ctxpopup_item_label_get(event_info));
+}
+
+#define ITEM_NEW(_hov, _label, _icon)                                           \
+   if(_icon)                                                                    \
+     {                                                                          \
+        ic = elm_icon_add(obj);                                                 \
+        elm_icon_standard_set(ic, _icon);                                       \
+        elm_icon_scale_set(ic, EINA_FALSE, EINA_FALSE);                         \
+     }                                                                          \
+   else                                                                         \
+      ic = NULL;                                                                \
+   it = elm_ctxpopup_item_append(_hov, _label, ic, _ctxpopup_item_cb, NULL);    \
+
+static void
+_list_item_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *ctxpopup, *ic;
+   Elm_Ctxpopup_Item *it;
+   Evas_Coord x,y;
+
+   ctxpopup = elm_ctxpopup_add(obj);
+
+   ITEM_NEW(ctxpopup, "Go to home folder", "home");
+   ITEM_NEW(ctxpopup, "Save file", "file");
+   ITEM_NEW(ctxpopup, "Delete file", "delete");
+   ITEM_NEW(ctxpopup, "Navigate to folder", "folder");
+   elm_ctxpopup_item_disabled_set(it, EINA_TRUE);
+   ITEM_NEW(ctxpopup, "Edit entry", "edit");
+   ITEM_NEW(ctxpopup, "Set date and time", "clock");
+   elm_ctxpopup_item_disabled_set(it, EINA_TRUE);
+
+   evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y);
+   evas_object_size_hint_max_set(ctxpopup, 240, 240);
+   evas_object_move(ctxpopup, x, y);
+   evas_object_show(ctxpopup);
+}
+
+static void
+_list_item_cb2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *ctxpopup, *ic;
+   Elm_Ctxpopup_Item *it;
+   Evas_Coord x,y;
+
+   ctxpopup = elm_ctxpopup_add(obj);
+
+   ITEM_NEW(ctxpopup, NULL, "home");
+   ITEM_NEW(ctxpopup, NULL, "file");
+   ITEM_NEW(ctxpopup, NULL, "delete");
+   ITEM_NEW(ctxpopup, NULL, "folder");
+   ITEM_NEW(ctxpopup, NULL, "edit");
+   elm_ctxpopup_item_disabled_set(it, EINA_TRUE);
+   ITEM_NEW(ctxpopup, NULL, "clock");
+
+   evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y);
+   evas_object_size_hint_max_set(ctxpopup, 240, 240);
+   evas_object_move(ctxpopup, x, y);
+   evas_object_show(ctxpopup);
+}
+
+static void
+_list_item_cb3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *ctxpopup, *ic;
+   Elm_Ctxpopup_Item *it;
+   Evas_Coord x,y;
+
+   ctxpopup = elm_ctxpopup_add(obj);
+
+   ITEM_NEW(ctxpopup, "Eina", NULL);
+   ITEM_NEW(ctxpopup, "Eet", NULL);
+   ITEM_NEW(ctxpopup, "Evas", NULL);
+   ITEM_NEW(ctxpopup, "Ecore", NULL);
+   elm_ctxpopup_item_disabled_set(it, EINA_TRUE);
+   ITEM_NEW(ctxpopup, "Embryo", NULL);
+   ITEM_NEW(ctxpopup, "Edje", NULL);
+
+   evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y);
+   evas_object_move(ctxpopup, x, y);
+   evas_object_show(ctxpopup);
+}
+
+static void
+_list_item_cb4(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *ctxpopup, *ic;
+   Elm_Ctxpopup_Item *it;
+   Evas_Coord x,y;
+
+   ctxpopup = elm_ctxpopup_add(obj);
+   elm_ctxpopup_horizontal_set(ctxpopup, EINA_TRUE);
+
+   ITEM_NEW(ctxpopup, NULL, "home");
+   ITEM_NEW(ctxpopup, NULL, "file");
+   ITEM_NEW(ctxpopup, NULL, "delete");
+   ITEM_NEW(ctxpopup, NULL, "folder");
+   ITEM_NEW(ctxpopup, NULL, "edit");
+   ITEM_NEW(ctxpopup, NULL, "clock");
+
+   evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y);
+   evas_object_size_hint_max_set(ctxpopup, 240, 240);
+   evas_object_move(ctxpopup, x, y);
+   evas_object_show(ctxpopup);
+}
+
+
+static void
+_list_item_cb5(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *ctxpopup, *btn;
+   Evas_Coord x,y;
+
+   btn = elm_button_add(obj);
+   elm_button_label_set(btn, "Enlightenment");
+   evas_object_size_hint_min_set(btn, 150, 150);
+
+   ctxpopup = elm_ctxpopup_add(obj);
+   elm_ctxpopup_content_set(ctxpopup, btn);
+
+   evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y);
+   evas_object_move(ctxpopup, x, y);
+   evas_object_show(ctxpopup);
+}
+
+
+static void _list_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   elm_list_item_selected_set(event_info, EINA_FALSE);
+}
+
+void
+test_ctxpopup(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *list;
+
+   win = elm_win_add(NULL, "Contexual Popup", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Contextual Popup");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   list = elm_list_add(win);
+   elm_win_resize_object_add(win, list);
+   elm_list_mode_set(list, ELM_LIST_COMPRESS);
+   evas_object_smart_callback_add(list, "selected", _list_clicked, NULL);
+
+#undef ITEM_NEW
+   elm_list_item_append(list, "Ctxpopup with icons and labels", NULL, NULL,
+                        _list_item_cb, NULL);
+   elm_list_item_append(list, "Ctxpopup with icons only", NULL, NULL,
+                        _list_item_cb2, NULL);
+   elm_list_item_append(list, "Ctxpopup with labels only", NULL, NULL,
+                        _list_item_cb3, NULL);
+   elm_list_item_append(list, "Ctxpopup at horizontal mode", NULL, NULL,
+                        _list_item_cb4, NULL);
+   elm_list_item_append(list, "Ctxpopup with user content", NULL, NULL,
+                        _list_item_cb5, NULL);
+   evas_object_show(list);
+   elm_list_go(list);
+
+   evas_object_resize(win, 400, 400);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_cursor.c b/src/bin/test_cursor.c
new file mode 100644 (file)
index 0000000..f45c552
--- /dev/null
@@ -0,0 +1,397 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct _Testitem
+{
+   Elm_Gengrid_Item *item;
+   const char *path;
+   int mode;
+   int onoff;
+} Testitem;
+
+static Elm_Gengrid_Item_Class gic;
+
+char *
+grd_lbl_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   const Testitem *ti = data;
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Photo %s", ti->path);
+   return strdup(buf);
+}
+
+Evas_Object *
+grd_icon_get(void *data, Evas_Object *obj, const char *part)
+{
+   const Testitem *ti = data;
+   if (!strcmp(part, "elm.swallow.icon"))
+     {
+        Evas_Object *icon = elm_bg_add(obj);
+        elm_bg_file_set(icon, ti->path, NULL);
+        evas_object_size_hint_aspect_set(icon, EVAS_ASPECT_CONTROL_VERTICAL,
+                                         1, 1);
+        evas_object_show(icon);
+        return icon;
+     }
+   return NULL;
+}
+
+static Elm_Genlist_Item_Class itct;
+
+static void
+glt_exp(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   Evas_Object *gl = elm_genlist_item_genlist_get(it);
+   int val = (int)(long)elm_genlist_item_data_get(it);
+   Elm_Genlist_Item *it1, *it2, *it3;
+
+   val *= 10;
+   it1 = elm_genlist_item_append(gl, &itct, (void *)(long)(val + 1), it,
+                                 ELM_GENLIST_ITEM_NONE, NULL, NULL);
+   it2 = elm_genlist_item_append(gl, &itct, (void *)(long)(val + 2), it,
+                                 ELM_GENLIST_ITEM_NONE, NULL, NULL);
+   it3 = elm_genlist_item_append(gl, &itct, (void *)(long)(val + 3), it,
+                                 ELM_GENLIST_ITEM_SUBITEMS, NULL, NULL);
+
+   elm_genlist_item_cursor_set(it1, ELM_CURSOR_HAND2);
+   elm_genlist_item_cursor_set(it2, ELM_CURSOR_HAND2);
+   elm_genlist_item_cursor_set(it3, ELM_CURSOR_HAND1);
+
+}
+
+static void
+glt_con(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_subitems_clear(it);
+}
+
+static void
+glt_exp_req(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 1);
+}
+
+static void
+glt_con_req(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 0);
+}
+
+char *
+glt_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item mode %i", (int)(long)data);
+   return strdup(buf);
+}
+
+void
+test_cursor(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt, *list, *entry, *ck;
+   Elm_List_Item *lit;
+
+   win = elm_win_add(NULL, "cursor", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Cursor");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+   elm_object_cursor_set(bg, ELM_CURSOR_CIRCLE);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ck = elm_clock_add(win);
+   elm_object_cursor_set(ck, ELM_CURSOR_CLOCK);
+   elm_box_pack_end(bx, ck);
+   evas_object_show(ck);
+
+   bt = elm_button_add(win);
+   elm_object_cursor_set(bt, ELM_CURSOR_COFFEE_MUG);
+   elm_button_label_set(bt, "Coffee Mug");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_object_cursor_set(bt, ELM_CURSOR_CLOCK);
+   elm_button_label_set(bt, "Cursor unset");
+   elm_object_cursor_unset(bt);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   list = elm_list_add(win);
+   elm_box_pack_end(bx, list);
+   evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_object_cursor_set(list, ELM_CURSOR_WATCH);
+   lit = elm_list_item_append(list, "watch over list | hand1", NULL, NULL, NULL,
+                        NULL);
+   elm_list_item_cursor_set(lit, ELM_CURSOR_HAND1);
+   lit = elm_list_item_append(list, "watch over list | hand2", NULL, NULL, NULL,
+                        NULL);
+   elm_list_item_cursor_set(lit, ELM_CURSOR_HAND2);
+   elm_list_go(list);
+   evas_object_show(list);
+
+   entry = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_entry_set(entry, "Xterm cursor");
+   elm_scrolled_entry_single_line_set(entry, EINA_TRUE);
+   evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_fill_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, entry);
+   evas_object_show(entry);
+   elm_object_cursor_set(entry, ELM_CURSOR_XTERM);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+void
+test_cursor2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *o, *grid, *gl;
+   Elm_Genlist_Item *it1, *it2, *it3;
+   Elm_Toolbar_Item *tit;
+   Elm_List_Item *lit;
+   char buf[PATH_MAX];
+   static Testitem ti[144];
+   int i, n;
+   const char *img[9] =
+     {
+        "panel_01.jpg",
+        "plant_01.jpg",
+        "rock_01.jpg",
+        "rock_02.jpg",
+        "sky_01.jpg",
+        "sky_02.jpg",
+        "sky_03.jpg",
+        "sky_04.jpg",
+        "wood_01.jpg",
+     };
+
+   win = elm_win_add(NULL, "cursor", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Cursor 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   o = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(o, 0);
+   evas_object_size_hint_weight_set(o, 0.0, 0.0);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.0);
+   tit = elm_toolbar_item_append(o, NULL, "Bogosity", NULL, NULL);
+   elm_toolbar_item_cursor_set(tit, ELM_CURSOR_BOGOSITY);
+   tit = elm_toolbar_item_append(o, NULL, "Unset", NULL, NULL);
+   elm_toolbar_item_cursor_set(tit, ELM_CURSOR_BOGOSITY);
+   elm_toolbar_item_cursor_unset(tit);
+   tit = elm_toolbar_item_append(o, NULL, "Xterm", NULL, NULL);
+   elm_toolbar_item_cursor_set(tit, ELM_CURSOR_XTERM);
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_list_add(win);
+   elm_box_pack_end(bx, o);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   lit = elm_list_item_append(o, "cursor bogosity", NULL, NULL,  NULL, NULL);
+   elm_list_item_cursor_set(lit, ELM_CURSOR_BOGOSITY);
+   lit = elm_list_item_append(o, "cursor unset", NULL, NULL,  NULL, NULL);
+   elm_list_item_cursor_set(lit, ELM_CURSOR_BOGOSITY);
+   elm_list_item_cursor_unset(lit);
+   lit = elm_list_item_append(o, "cursor xterm", NULL, NULL,  NULL, NULL);
+   elm_list_item_cursor_set(lit, ELM_CURSOR_XTERM);
+   elm_list_go(o);
+   evas_object_show(o);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(gl);
+
+   itct.item_style     = "default";
+   itct.func.label_get = glt_label_get;
+
+   it1 = elm_genlist_item_append(gl, &itct, (void *) 1, NULL,
+                                 ELM_GENLIST_ITEM_SUBITEMS, NULL, NULL);
+   it2 = elm_genlist_item_append(gl, &itct, (void *) 2, NULL,
+                                 ELM_GENLIST_ITEM_SUBITEMS, NULL, NULL);
+   it3 = elm_genlist_item_append(gl, &itct, (void *) 3, NULL,
+                                 ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+   elm_genlist_item_cursor_set(it1, ELM_CURSOR_HAND1);
+   elm_genlist_item_cursor_set(it2, ELM_CURSOR_HAND1);
+   elm_genlist_item_cursor_set(it3, ELM_CURSOR_CROSS);
+
+   evas_object_smart_callback_add(gl, "expand,request", glt_exp_req, gl);
+   evas_object_smart_callback_add(gl, "contract,request", glt_con_req, gl);
+   evas_object_smart_callback_add(gl, "expanded", glt_exp, gl);
+   evas_object_smart_callback_add(gl, "contracted", glt_con, gl);
+
+   elm_box_pack_end(bx, gl);
+
+   grid = elm_gengrid_add(win);
+   elm_gengrid_item_size_set(grid, 130, 130);
+   elm_gengrid_horizontal_set(grid, EINA_FALSE);
+   elm_gengrid_multi_select_set(grid, EINA_TRUE);
+   evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   gic.item_style = "default";
+   gic.func.label_get = grd_lbl_get;
+   gic.func.icon_get = grd_icon_get;
+
+   n = 0;
+   for (i = 0; i < 3 * 3; i++)
+     {
+        snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, img[n]);
+        n = (n + 1) % 9;
+        ti[i].mode = i;
+        ti[i].path = eina_stringshare_add(buf);
+        ti[i].item = elm_gengrid_item_append(grid, &gic, &(ti[i]), NULL, NULL);
+        if (n % 2)
+           elm_gengrid_item_cursor_set(ti[i].item, ELM_CURSOR_HAND1);
+        else
+           elm_gengrid_item_cursor_set(ti[i].item, ELM_CURSOR_CLOCK);
+        if (!(i % 5))
+           elm_gengrid_item_selected_set(ti[i].item, EINA_TRUE);
+     }
+   elm_box_pack_end(bx, grid);
+   evas_object_show(grid);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+void
+test_cursor3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *o;
+   Elm_List_Item *lit;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "cursor", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Cursor 3");
+   elm_win_autodel_set(win, 1);
+
+   snprintf(buf, sizeof(buf), "%s/objects/cursors.edj", PACKAGE_DATA_DIR);
+   elm_theme_extension_add(NULL, buf);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, ELM_CURSOR_HAND1);
+   elm_object_cursor_engine_only_set(o, EINA_FALSE);
+   elm_button_label_set(o, "hand1");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, ELM_CURSOR_HAND2);
+   elm_button_label_set(o, "hand2 x");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, ELM_CURSOR_HAND2);
+   elm_object_cursor_engine_only_set(o, EINA_FALSE);
+   elm_button_label_set(o, "hand2");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, "hand3");
+   elm_object_cursor_engine_only_set(o, EINA_FALSE);
+   elm_button_label_set(o, "hand3");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, "hand3");
+   elm_object_cursor_engine_only_set(o, EINA_FALSE);
+   elm_object_cursor_style_set(o, "transparent");
+   elm_button_label_set(o, "hand3 transparent");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, "hand3");
+   elm_object_cursor_engine_only_set(o, EINA_FALSE);
+   elm_object_cursor_unset(o);
+   elm_button_label_set(o, "unset");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, "hand4");
+   elm_button_label_set(o, "not existent");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   elm_cursor_engine_only_set(0);
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, "hand2");
+   elm_button_label_set(o, "hand 2 engine only config false");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   elm_cursor_engine_only_set(1);
+   o = elm_button_add(win);
+   elm_object_cursor_set(o, "hand2");
+   elm_button_label_set(o, "hand 2 engine only config true");
+   elm_box_pack_end(bx, o);
+   evas_object_show(o);
+
+   o = elm_list_add(win);
+   elm_box_pack_end(bx, o);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   lit = elm_list_item_append(o, "cursor hand2 x", NULL, NULL,  NULL, NULL);
+   elm_list_item_cursor_set(lit, ELM_CURSOR_HAND2);
+   lit = elm_list_item_append(o, "cursor hand2", NULL, NULL,  NULL, NULL);
+   elm_list_item_cursor_set(lit, ELM_CURSOR_HAND2);
+   elm_list_item_cursor_engine_only_set(lit, EINA_FALSE);
+   lit = elm_list_item_append(o, "cursor hand3", NULL, NULL,  NULL, NULL);
+   elm_list_item_cursor_set(lit, "hand3");
+   elm_list_item_cursor_engine_only_set(lit, EINA_FALSE);
+   lit = elm_list_item_append(o, "cursor hand3 transparent", NULL, NULL,
+                              NULL, NULL);
+   elm_list_item_cursor_set(lit, "hand3");
+   elm_list_item_cursor_style_set(lit, "transparent");
+   elm_list_item_cursor_engine_only_set(lit, EINA_FALSE);
+   elm_list_go(o);
+   evas_object_show(o);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_diskselector.c b/src/bin/test_diskselector.c
new file mode 100644 (file)
index 0000000..9312c2b
--- /dev/null
@@ -0,0 +1,131 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+_disk_sel(void *data __UNUSED__, Evas_Object * obj __UNUSED__, void *event_info)
+{
+   Elm_Diskselector_Item *it = event_info;
+   printf("Equinox: %s\n", elm_diskselector_item_label_get(it));
+}
+
+static void
+_disk_next(void *data __UNUSED__, Evas_Object * obj __UNUSED__, void *event_info)
+{
+   Elm_Diskselector_Item *next, *prev, *it = event_info;
+   prev = elm_diskselector_item_prev_get(it);
+   next = elm_diskselector_item_next_get(it);
+   printf("Prev: %s, Next: %s\n", elm_diskselector_item_label_get(prev),
+          elm_diskselector_item_label_get(next));
+}
+
+static void
+_print_disk_info_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Diskselector_Item *it = event_info;
+   printf("Selected label: %s\n", elm_diskselector_item_label_get(it));
+}
+
+static Evas_Object *
+_disk_create(Evas_Object *win, Eina_Bool round)
+{
+   Elm_Diskselector_Item *it;
+   Evas_Object *di;
+
+   di = elm_diskselector_add(win);
+
+   elm_diskselector_item_append(di, "January", NULL, NULL, NULL);
+   elm_diskselector_item_append(di, "February", NULL, _disk_next, NULL);
+   elm_diskselector_item_append(di, "March", NULL, _disk_sel, NULL);
+   elm_diskselector_item_append(di, "April", NULL, NULL, NULL);
+   elm_diskselector_item_append(di, "May", NULL, NULL, NULL);
+   elm_diskselector_item_append(di, "June", NULL, NULL, NULL);
+   elm_diskselector_item_append(di, "July", NULL, NULL, NULL);
+   it = elm_diskselector_item_append(di, "August", NULL, NULL, NULL);
+   elm_diskselector_item_append(di, "September", NULL, _disk_sel, NULL);
+   elm_diskselector_item_append(di, "October", NULL, NULL, NULL);
+   elm_diskselector_item_append(di, "November", NULL, NULL, NULL);
+   elm_diskselector_item_append(di, "December", NULL, NULL, NULL);
+
+   elm_diskselector_item_selected_set(it, EINA_TRUE);
+   elm_diskselector_round_set(di, round);
+
+   return di;
+}
+
+void
+test_diskselector(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *disk, *ic;
+   Elm_Diskselector_Item *it;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "diskselector", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Disk Selector");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bg, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(bx);
+
+   disk = _disk_create(win, EINA_TRUE);
+   evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, disk);
+   evas_object_show(disk);
+   evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL);
+   it = elm_diskselector_selected_item_get(disk);
+   elm_diskselector_item_selected_set(it, EINA_FALSE);
+
+   disk = _disk_create(win, EINA_FALSE);
+   evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, disk);
+   evas_object_show(disk);
+   evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL);
+   it = elm_diskselector_first_item_get(disk);
+   it = elm_diskselector_item_next_get(it);
+   elm_diskselector_item_selected_set(it, EINA_TRUE);
+
+   disk = _disk_create(win, EINA_FALSE);
+   evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, disk);
+   evas_object_show(disk);
+   evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL);
+   elm_diskselector_side_label_lenght_set(disk, 4);
+
+   disk = elm_diskselector_add(win);
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 1, 1);
+   elm_diskselector_item_append(disk, "Sunday", ic, NULL, NULL);
+   elm_diskselector_item_append(disk, "Monday", NULL, NULL, NULL);
+   elm_diskselector_item_append(disk, "Tuesday", NULL, NULL, NULL);
+   elm_diskselector_item_append(disk, "Wednesday", NULL, NULL, NULL);
+   elm_diskselector_item_append(disk, "Thursday", NULL, NULL, NULL);
+   elm_diskselector_item_append(disk, "Friday", NULL, NULL, NULL);
+   elm_diskselector_item_append(disk, "Saturday", NULL, NULL, NULL);
+   elm_diskselector_round_set(disk, EINA_TRUE);
+   evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, disk);
+   evas_object_show(disk);
+   evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_entry.c b/src/bin/test_entry.c
new file mode 100644 (file)
index 0000000..0d44331
--- /dev/null
@@ -0,0 +1,1644 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+my_entry_bt_1(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_entry_entry_set(en, "");
+}
+
+static void
+my_entry_bt_2(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   const char *s = elm_entry_entry_get(en);
+   printf("ENTRY:\n");
+   if (s) printf("%s\n", s);
+   printf("ENTRY PLAIN UTF8:\n");
+   if (s)
+     {
+        s = elm_entry_markup_to_utf8(s);
+        if (s)
+          {
+             printf("%s\n", s);
+             free((char *)s);
+          }
+     }
+}
+
+static void
+my_entry_bt_3(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   const char *s = elm_entry_selection_get(en);
+   printf("SELECTION:\n");
+   if (s) printf("%s\n", s);
+   printf("SELECTION PLAIN UTF8:\n");
+   if (s)
+     {
+        s = elm_entry_markup_to_utf8(s);
+        if (s)
+          {
+             printf("%s\n", s);
+             free((char *)s);
+          }
+     }
+}
+
+static void
+my_entry_bt_4(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_entry_entry_insert(en, "Insert some <b>BOLD</> text");
+}
+
+void
+test_entry(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *bt, *en;
+   char buf[4096];
+
+   win = elm_win_add(NULL, "entry", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Entry");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   en = elm_entry_add(win);
+   elm_entry_line_wrap_set(en, 0);
+   snprintf(buf, sizeof(buf),
+            "This is an entry widget in this window that<br>"
+            "uses markup <b>like this</> for styling and<br>"
+            "formatting <em>like this</>, as well as<br>"
+            "<a href=X><link>links in the text</></a>, so enter text<br>"
+            "in here to edit it. By the way, links are<br>"
+            "called <a href=anc-02>Anchors</a> so you will need<br>"
+            "to refer to them this way.<br>"
+            "<br>"
+            
+            "Also you can stick in items with (relsize + ascent): "
+            "<item relsize=16x16 vsize=ascent href=emoticon/evil-laugh></item>"
+            " (full) "
+            "<item relsize=16x16 vsize=full href=emoticon/guilty-smile></item>"
+            " (to the left)<br>"
+            
+            "Also (size + ascent): "
+            "<item size=16x16 vsize=ascent href=emoticon/haha></item>"
+            " (full) "
+            "<item size=16x16 vsize=full href=emoticon/happy-panting></item>"
+            " (before this)<br>"
+            
+            "And as well (absize + ascent): "
+            "<item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item>"
+            " (full) "
+            "<item absize=64x64 vsize=full href=emoticon/not-impressed></item>"
+            " or even paths to image files on disk too like: "
+            "<item absize=96x128 vsize=full href=file://%s/images/sky_01.jpg></item>"
+            " ... end."
+            , PACKAGE_DATA_DIR
+            );
+   elm_entry_entry_set(en, buf);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, en);
+   evas_object_show(en);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clear");
+   evas_object_smart_callback_add(bt, "clicked", my_entry_bt_1, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Print");
+   evas_object_smart_callback_add(bt, "clicked", my_entry_bt_2, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Selection");
+   evas_object_smart_callback_add(bt, "clicked", my_entry_bt_3, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Insert");
+   evas_object_smart_callback_add(bt, "clicked", my_entry_bt_4, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   elm_object_focus(en);
+   evas_object_show(win);
+}
+
+static void
+my_scrolled_entry_bt_1(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_entry_set(en, "");
+}
+
+static void
+my_scrolled_entry_bt_2(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   const char *s = elm_scrolled_entry_entry_get(en);
+   printf("ENTRY:\n");
+   if (s) printf("%s\n", s);
+   printf("ENTRY PLAIN UTF8:\n");
+   if (s)
+     {
+        s = elm_entry_markup_to_utf8(s);
+        if (s)
+          {
+             printf("%s\n", s);
+             free((char *)s);
+          }
+     }
+}
+
+static void
+my_scrolled_entry_bt_3(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   const char *s = elm_scrolled_entry_selection_get(en);
+   printf("SELECTION:\n");
+   if (s) printf("%s\n", s);
+   printf("SELECTION PLAIN UTF8:\n");
+   if (s)
+     {
+        s = elm_entry_markup_to_utf8(s);
+        if (s)
+          {
+             printf("%s\n", s);
+             free((char *)s);
+          }
+     }
+}
+
+static void
+my_scrolled_entry_bt_4(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_entry_insert(en, "Insert some <b>BOLD</> text");
+}
+
+static void
+my_scrolled_entry_bt_5(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   const char *s = elm_scrolled_entry_entry_get(en);
+   printf("PASSWORD: '%s'\n", s ? s : "");
+}
+
+static void
+scrolled_anchor_test(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_entry_insert(en, "ANCHOR CLICKED");
+}
+
+void
+test_entry_scrolled(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *bt, *en, *en_p, *sp;
+   static Elm_Entry_Filter_Accept_Set digits_filter_data, digits_filter_data2;
+   static Elm_Entry_Filter_Limit_Size limit_filter_data, limit_filter_data2;
+
+   win = elm_win_add(NULL, "entry-scrolled", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Entry Scrolled");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   /* disabled entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_entry_set(en, "Disabled entry");
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_object_disabled_set(en, 1);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   /* password entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_password_set(en, 1);
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_scrolled_entry_entry_set(en, "Access denied, give up!");
+   elm_object_disabled_set(en, 1);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   /* multi-line disable entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_ON, ELM_SCROLLER_POLICY_ON);
+   elm_object_disabled_set(en, 1);
+   elm_scrolled_entry_context_menu_item_add(en, "Hello", NULL, ELM_ICON_NONE, NULL, NULL);
+   elm_scrolled_entry_context_menu_item_add(en, "World", NULL, ELM_ICON_NONE, NULL, NULL);
+   elm_scrolled_entry_entry_set(en,
+                               "Multi-line disabled entry widget :)<br>"
+                               "We can use markup <b>like this</> for styling and<br>"
+                               "formatting <em>like this</>, as well as<br>"
+                               "<a href=X><link>links in the text</></a>,"
+                               "but it won't be editable or clickable.");
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   /* Single line selected entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_entry_set(en, "This is a single line");
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_scrolled_entry_select_all(en);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   /* Only digits entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_entry_set(en, "01234");
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_single_line_set(en, 1);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   digits_filter_data.accepted = "0123456789";
+   digits_filter_data.rejected = NULL;
+   elm_scrolled_entry_text_filter_append(en, elm_entry_filter_accept_set, &digits_filter_data);
+
+   /* No digits entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_entry_set(en, "No numbers here");
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_single_line_set(en, 1);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   digits_filter_data2.accepted = NULL;
+   digits_filter_data2.rejected = "0123456789";
+   elm_scrolled_entry_text_filter_append(en, elm_entry_filter_accept_set, &digits_filter_data2);
+
+   /* Size limited entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_entry_set(en, "Just 20 chars");
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_single_line_set(en, 1);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   limit_filter_data.max_char_count = 20;
+   limit_filter_data.max_byte_count = 0;
+   elm_scrolled_entry_text_filter_append(en, elm_entry_filter_limit_size, &limit_filter_data);
+
+   /* Byte size limited entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_entry_set(en, "And now only 30 bytes");
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_single_line_set(en, 1);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   limit_filter_data2.max_char_count = 0;
+   limit_filter_data2.max_byte_count = 30;
+   elm_scrolled_entry_text_filter_append(en, elm_entry_filter_limit_size, &limit_filter_data2);
+
+   /* Single line password entry */
+   en_p = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en_p, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en_p, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(en_p, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_entry_set(en_p, "Password here");
+   elm_scrolled_entry_single_line_set(en_p, 1);
+   elm_scrolled_entry_password_set(en_p, 1);
+   evas_object_show(en_p);
+   elm_box_pack_end(bx, en_p);
+
+   /* scrolled entry with icon/end widgets*/
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_single_line_set(en, 1);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   bt = elm_icon_add(win);
+   elm_icon_standard_set(bt, "home");
+   evas_object_size_hint_min_set(bt, 48, 48);
+   evas_object_color_set(bt, 255, 0, 0, 128);
+   evas_object_show(bt);
+   elm_scrolled_entry_icon_set(en, bt);
+   bt = elm_icon_add(win);
+   elm_icon_standard_set(bt, "delete");
+   evas_object_color_set(bt, 255, 0, 0, 128);
+   evas_object_size_hint_min_set(bt, 48, 48);
+   evas_object_show(bt);
+   elm_scrolled_entry_end_set(en, bt);
+   elm_scrolled_entry_entry_set(en, "scrolled entry with icon and end objects");
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   /* markup scrolled entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_ON, ELM_SCROLLER_POLICY_ON);
+   elm_scrolled_entry_entry_set(en,
+                               "This is an entry widget in this window that<br>"
+                               "uses markup <b>like this</> for styling and<br>"
+                               "formatting <em>like this</>, as well as<br>"
+                               "<a href=X><link>links in the text</></a>, so enter text<br>"
+                               "in here to edit it. By them way, links are<br>"
+                               "called <a href=anc-02>Anchors</a> so you will need<br>"
+                               "to refer to them this way. At the end here is a really long "
+                               "line to test line wrapping to see if it works. But just in "
+                               "case this line is not long enough I will add more here to "
+                               "really test it out, as Elementary really needs some "
+                               "good testing to see if entry widgets work as advertised.");
+   evas_object_smart_callback_add(en, "anchor,clicked", scrolled_anchor_test, en);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clear");
+   evas_object_smart_callback_add(bt, "clicked", my_scrolled_entry_bt_1, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Print");
+   evas_object_smart_callback_add(bt, "clicked", my_scrolled_entry_bt_2, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Print pwd");
+   evas_object_smart_callback_add(bt, "clicked", my_scrolled_entry_bt_5, en_p);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Selection");
+   evas_object_smart_callback_add(bt, "clicked", my_scrolled_entry_bt_3, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Insert");
+   evas_object_smart_callback_add(bt, "clicked", my_scrolled_entry_bt_4, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 300);
+
+   elm_object_focus(win);
+   evas_object_show(win);
+}
+
+static void
+my_ent_bt_clr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_entry_set(en, "");
+}
+
+static void
+my_ent_bt_pri(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   const char *s = elm_scrolled_entry_entry_get(en);
+   printf("ENTRY:\n");
+   if (s) printf("%s\n", s);
+   printf("ENTRY PLAIN UTF8:\n");
+   if (s)
+     {
+        s = elm_entry_markup_to_utf8(s);
+        if (s)
+          {
+             printf("%s\n", s);
+             free((char *)s);
+          }
+     }
+}
+
+static void
+my_ent_bt_sel(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   const char *s = elm_scrolled_entry_selection_get(en);
+   printf("SELECTION:\n");
+   if (s) printf("%s\n", s);
+   printf("SELECTION PLAIN UTF8:\n");
+   if (s)
+     {
+        s = elm_entry_markup_to_utf8(s);
+        if (s)
+          {
+             printf("%s\n", s);
+             free((char *)s);
+          }
+     }
+}
+
+static void
+my_ent_bt_all(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_select_all(en);
+}
+
+static void
+my_ent_bt_non(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_select_none(en);
+}
+
+static void
+my_ent_bt_ins(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_entry_insert(en, "Insert text");
+}
+
+static void
+my_ent_bt_lef(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_prev(en);
+}
+
+static void
+my_ent_bt_rig(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_next(en);
+}
+
+static void
+my_ent_bt_up_(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_up(en);
+}
+
+static void
+my_ent_bt_dow(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_down(en);
+}
+
+static void
+my_ent_bt_beg(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_begin_set(en);
+}
+
+static void
+my_ent_bt_end(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_end_set(en);
+}
+
+static void
+my_ent_bt_lbe(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_line_begin_set(en);
+}
+
+static void
+my_ent_bt_len(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_line_end_set(en);
+}
+
+static void
+my_ent_bt_sbe(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_selection_begin(en);
+}
+
+static void
+my_ent_bt_sen(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_cursor_selection_end(en);
+}
+
+static void
+my_ent_bt_fmt(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   printf("IS FORMAT: %i\n", 
+          (int)elm_scrolled_entry_cursor_is_format_get(en));
+}
+
+static void
+my_ent_bt_vfm(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   printf("IS VISIBLE FORMAT %i\n",
+          (int)elm_scrolled_entry_cursor_is_visible_format_get(en));
+}
+
+static void
+my_ent_bt_chr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   printf("CHAR '%s'\n", elm_scrolled_entry_cursor_content_get(en));
+}
+
+static void
+my_ent_bt_cut(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_selection_cut(en);
+}
+
+static void
+my_ent_bt_cop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_selection_copy(en);
+}
+
+static void
+my_ent_bt_pas(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_selection_paste(en);
+}
+
+void
+test_entry3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *bt, *en;
+
+   win = elm_win_add(NULL, "entry3", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Entry 3");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   /* Single line selected entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_entry_set(en, "This is a single line");
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_box_pack_end(bx, en);
+   evas_object_show(en);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clr");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_clr, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Pri");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_pri, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Sel");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sel, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "All");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_all, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Non");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_non, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Ins");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_ins, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Lef");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_lef, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rig");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_rig, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Up ");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_up_, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Dow");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_dow, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Beg");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_beg, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "End");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_end, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "LBe");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_lbe, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "LEn");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_len, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "SBe");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sbe, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "SEn");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sen, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Fmt");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_fmt, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "VFm");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_vfm, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Chr");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_chr, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Cut");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_cut, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Cop");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_cop, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Pas");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_pas, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   /* markup scrolled entry */
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scrolled_entry_entry_set(en,
+                               "This is an entry widget in this window that<br>"
+                               "uses markup <b>like this</> for styling and<br>"
+                               "formatting <em>like this</>, as well as<br>"
+                               "<a href=X><link>links in the text</></a>, so enter text<br>"
+                               "in here to edit it. By them way, links are<br>"
+                               "called <a href=anc-02>Anchors</a> so you will need<br>"
+                               "to refer to them this way. At the end here is a really long "
+                               "line to test line wrapping to see if it works. But just in "
+                               "case this line is not long enough I will add more here to "
+                               "really test it out, as Elementary really needs some "
+                               "good testing to see if entry widgets work as advertised."
+                                );
+   evas_object_smart_callback_add(en, "anchor,clicked", scrolled_anchor_test, en);
+   elm_box_pack_end(bx, en);
+   evas_object_show(en);
+   
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clr");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_clr, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Pri");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_pri, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Sel");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sel, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "All");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_all, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Non");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_non, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Ins");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_ins, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Lef");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_lef, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rig");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_rig, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Up ");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_up_, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Dow");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_dow, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Beg");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_beg, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "End");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_end, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "LBe");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_lbe, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "LEn");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_len, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "SBe");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sbe, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "SEn");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sen, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Fmt");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_fmt, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "VFm");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_vfm, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Chr");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_chr, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Cut");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_cut, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Cop");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_cop, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Pas");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_pas, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt); 
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 480);
+
+   elm_object_focus(win);
+   evas_object_show(win);
+}
+
+void
+test_entry4(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *ly, *en;
+   char buf[PATH_MAX];
+   
+   win = elm_win_add(NULL, "entry4", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Entry 4");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   ly = elm_layout_add(win);
+   snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+   elm_layout_file_set(ly, buf, "layout");
+   evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, ly);
+   evas_object_show(ly);
+   
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_entry_set(en, "This is a single line");
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_layout_content_set(ly, "element1", en);
+   evas_object_show(en);
+   
+   en = elm_entry_add(win);
+   elm_entry_line_wrap_set(en, 0);
+   elm_entry_entry_set(en,
+                      "This is an entry widget<br>"
+                      "that uses markup<br>"
+                       "<b>like this</> and has<br>"
+                      "no scroller, so you can<br>"
+                      "use it more flexibly.");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_layout_content_set(ly, "element2", en);
+   evas_object_show(en);
+
+   en = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scrolled_entry_entry_set(en,
+                               "This is an entry widget in this window that<br>"
+                               "uses markup <b>like this</> for styling and<br>"
+                               "formatting <em>like this</>, as well as<br>"
+                               "<a href=X><link>links in the text</></a>, so enter text<br>"
+                               "in here to edit it. By them way, links are<br>"
+                               "called <a href=anc-02>Anchors</a> so you will need<br>"
+                               "to refer to them this way. At the end here is a really long "
+                               "line to test line wrapping to see if it works. But just in "
+                               "case this line is not long enough I will add more here to "
+                               "really test it out, as Elementary really needs some "
+                               "good testing to see if entry widgets work as advertised."
+                                );
+   evas_object_smart_callback_add(en, "anchor,clicked", scrolled_anchor_test, en);
+   elm_layout_content_set(ly, "element3", en);
+   evas_object_show(en);
+
+   evas_object_show(win);
+}
+
+void
+test_entry5(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *bt, *en;
+
+   win = elm_win_add(NULL, "entry5", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Entry 5");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_line_char_wrap_set(en, 1);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scrolled_entry_entry_set(en,
+                               "This is an entry widget in this window that "
+                               "uses markup like this for styling and "
+                               "formatting like this, as well as "
+                               "to refer to them this way. At the end here is a really long "
+                               "line to test line wrapping to see if it works. But just in "
+                               "case this line is not long enough I will add more here to "
+                               "really test it out, as Elementary really needs some "
+                               "good testing to see if entry widgets work as advertised."
+                                );
+   evas_object_smart_callback_add(en, "anchor,clicked", scrolled_anchor_test, en);
+   elm_box_pack_end(bx, en);
+   evas_object_show(en);
+   
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clr");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_clr, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Pri");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_pri, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Sel");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sel, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "All");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_all, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Non");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_non, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Ins");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_ins, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Lef");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_lef, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rig");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_rig, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Up ");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_up_, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Dow");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_dow, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Beg");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_beg, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "End");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_end, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "LBe");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_lbe, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "LEn");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_len, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "SBe");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sbe, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "SEn");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_sen, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Fmt");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_fmt, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "VFm");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_vfm, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Chr");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_chr, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Cut");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_cut, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Cop");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_cop, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Pas");
+   evas_object_smart_callback_add(bt, "clicked", my_ent_bt_pas, en);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt); 
+   evas_object_propagate_events_set(bt, 0);
+   elm_object_focus_allow_set(bt, 0);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 480);
+
+   elm_object_focus(win);
+   evas_object_show(win);
+}
+
+static void
+_scrolled_entry_clear(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *en = data;
+   elm_scrolled_entry_entry_set(en, "");
+}
+
+void
+test_entry_notepad(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *bt, *np;
+
+   win = elm_win_add(NULL, "entry-notepad", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Entry Notepad");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   np = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_file_set(np, "note.txt", ELM_TEXT_FORMAT_PLAIN_UTF8);
+   evas_object_size_hint_weight_set(np, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(np, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, np);
+   evas_object_show(np);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, EINA_TRUE);
+   elm_box_homogenous_set(bx2, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clear");
+   evas_object_smart_callback_add(bt, "clicked", _scrolled_entry_clear, np);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 300);
+
+   elm_object_focus(win);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_fileselector.c b/src/bin/test_fileselector.c
new file mode 100644 (file)
index 0000000..9a18756
--- /dev/null
@@ -0,0 +1,210 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+my_fileselector_done(void            *data,
+                     Evas_Object *obj __UNUSED__,
+                     void            *event_info)
+{
+   /* event_info conatin the full path of the selected file
+    * or NULL if none is selected or cancel is pressed */
+    const char *selected = event_info;
+
+    if (selected)
+      printf("Selected file: %s\n", selected);
+    else
+      evas_object_del(data);  /* delete the test window */
+}
+
+static void
+my_fileselector_selected(void *data   __UNUSED__,
+                         Evas_Object *obj,
+                         void        *event_info)
+{
+   /* event_info conatin the full path of the selected file */
+   const char *selected = event_info;
+   printf("Selected file: %s\n", selected);
+
+   /* or you can query the selection */
+   printf("or: %s\n", elm_fileselector_selected_get(obj));
+}
+
+static void
+_is_save_clicked(void            *data,
+                 Evas_Object *obj __UNUSED__,
+                 void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   printf("Toggle Is save\n");
+   if (elm_fileselector_is_save_get(fs))
+     elm_fileselector_is_save_set(fs, EINA_FALSE);
+   else
+     elm_fileselector_is_save_set(fs, EINA_TRUE);
+}
+
+static void
+_folder_only_clicked(void            *data,
+                     Evas_Object *obj __UNUSED__,
+                     void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   printf("Toggle Folder only\n");
+   if (elm_fileselector_folder_only_get(fs))
+     elm_fileselector_folder_only_set(fs, EINA_FALSE);
+   else
+     elm_fileselector_folder_only_set(fs, EINA_TRUE);
+}
+
+static void
+_expandable_clicked(void            *data,
+                    Evas_Object *obj __UNUSED__,
+                    void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   printf("Toggle Expandable\n");
+   if (elm_fileselector_expandable_get(fs))
+     elm_fileselector_expandable_set(fs, EINA_FALSE);
+   else
+     elm_fileselector_expandable_set(fs, EINA_TRUE);
+}
+
+static void
+_sel_get_clicked(void            *data,
+                 Evas_Object *obj __UNUSED__,
+                 void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   printf("Get Selected: %s\n", elm_fileselector_selected_get(fs));
+}
+
+static void
+_path_get_clicked(void            *data,
+                  Evas_Object *obj __UNUSED__,
+                  void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   printf("Get Path: %s\n", elm_fileselector_path_get(fs));
+}
+
+static void
+_mode_cycle_clicked(void            *data,
+                    Evas_Object *obj __UNUSED__,
+                    void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   Elm_Fileselector_Mode mode;
+
+   mode = (elm_fileselector_mode_get(fs) + 1) % ELM_FILESELECTOR_LAST;
+   elm_fileselector_mode_set(fs, mode);
+
+   printf("Setting mode to: %d\n", mode);
+}
+
+void
+test_fileselector(void *data       __UNUSED__,
+                  Evas_Object *obj __UNUSED__,
+                  void *event_info __UNUSED__)
+{
+   Evas_Object *win, *fs, *bg, *vbox, *hbox, *bt, *sep;
+
+   /* Set the locale according to the system pref.
+    * If you dont do so the file selector will order the files list in
+    * a case sensitive manner
+    */
+   setlocale(LC_ALL, "");
+
+   win = elm_win_add(NULL, "fileselector", ELM_WIN_BASIC);
+   elm_win_title_set(win, "File Selector");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   vbox = elm_box_add(win);
+   elm_win_resize_object_add(win, vbox);
+   evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(vbox);
+
+   fs = elm_fileselector_add(win);
+   /* enable the fs file name entry */
+   elm_fileselector_is_save_set(fs, EINA_TRUE);
+   /* make the file list a tree with dir expandable in place */
+   elm_fileselector_expandable_set(fs, EINA_FALSE);
+   /* start the fileselector in the home dir */
+   elm_fileselector_path_set(fs, getenv("HOME"));
+   /* allow fs to expand in x & y */
+   evas_object_size_hint_weight_set(fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fs, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(vbox, fs);
+   evas_object_show(fs); // TODO fix this is the widget
+
+   /* the 'done' cb is called when the user press ok/cancel */
+   evas_object_smart_callback_add(fs, "done", my_fileselector_done, win);
+   /* the 'selected' cb is called when the user click on a file/dir */
+   evas_object_smart_callback_add(fs, "selected", my_fileselector_selected,
+                                  win);
+
+   /* test buttons */
+   sep = elm_separator_add(win);
+   elm_separator_horizontal_set(sep, EINA_TRUE);
+   elm_box_pack_end(vbox, sep);
+   evas_object_show(sep);
+
+   hbox = elm_box_add(win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   elm_box_pack_end(vbox, hbox);
+   evas_object_show(hbox);
+
+   bt = elm_check_add(win);
+   elm_check_label_set(bt, "is save");
+   elm_check_state_set(bt, elm_fileselector_is_save_get(fs));
+   evas_object_smart_callback_add(bt, "changed", _is_save_clicked, fs);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_check_add(win);
+   elm_check_label_set(bt, "folder only");
+   elm_check_state_set(bt, elm_fileselector_folder_only_get(fs));
+   evas_object_smart_callback_add(bt, "changed", _folder_only_clicked, fs);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_check_add(win);
+   elm_check_label_set(bt, "expandable");
+   elm_check_state_set(bt, elm_fileselector_expandable_get(fs));
+   evas_object_smart_callback_add(bt, "changed", _expandable_clicked, fs);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   hbox = elm_box_add(win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   elm_box_pack_end(vbox, hbox);
+   evas_object_show(hbox);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "selected get");
+   evas_object_smart_callback_add(bt, "clicked", _sel_get_clicked, fs);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "path get");
+   evas_object_smart_callback_add(bt, "clicked", _path_get_clicked, fs);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "mode cycle");
+   evas_object_smart_callback_add(bt, "clicked", _mode_cycle_clicked, fs);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   evas_object_resize(win, 240, 350);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_fileselector_button.c b/src/bin/test_fileselector_button.c
new file mode 100644 (file)
index 0000000..00c8d07
--- /dev/null
@@ -0,0 +1,147 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+_file_chosen(void            *data,
+             Evas_Object *obj __UNUSED__,
+             void            *event_info)
+{
+   Evas_Object *entry = data;
+   const char *file = event_info;
+   if (file)
+     {
+        elm_entry_entry_set(entry, file);
+        printf("File chosen: %s\n", file);
+     }
+   else
+     printf("File selection canceled.\n");
+}
+
+static void
+_inwin_mode_toggle(void            *data,
+                   Evas_Object *obj __UNUSED__,
+                   void *event_info __UNUSED__)
+{
+   Evas_Object *fs_bt = data;
+   Eina_Bool value = elm_fileselector_button_inwin_mode_get(fs_bt);
+   elm_fileselector_button_inwin_mode_set(fs_bt, !value);
+   printf("Inwin mode set to: %s\n", value ? "false" : "true");
+}
+
+static void
+_current_sel_toggle(void            *data,
+                    Evas_Object *obj __UNUSED__,
+                    void *event_info __UNUSED__)
+{
+   Evas_Object *fs_bt = data;
+   Eina_Bool value = elm_fileselector_button_is_save_get(fs_bt);
+   elm_fileselector_button_is_save_set(fs_bt, !value);
+   printf("Current selection editable entry set to: %s\n",
+          value ? "false" : "true");
+}
+
+static void
+_folder_only_toggle(void            *data,
+                    Evas_Object *obj __UNUSED__,
+                    void *event_info __UNUSED__)
+{
+   Evas_Object *fs_bt = data;
+   Eina_Bool value = elm_fileselector_button_folder_only_get(fs_bt);
+   elm_fileselector_button_folder_only_set(fs_bt, !value);
+   printf("Folder only flag set to: %s\n", value ? "false" : "true");
+}
+
+static void
+_expandable_toggle(void            *data,
+                   Evas_Object *obj __UNUSED__,
+                   void *event_info __UNUSED__)
+{
+   Evas_Object *fs_bt = data;
+   Eina_Bool value = elm_fileselector_button_expandable_get(fs_bt);
+   elm_fileselector_button_expandable_set(fs_bt, !value);
+   printf("Expandable flag set to: %s\n", value ? "false" : "true");
+}
+
+void
+test_fileselector_button(void *data       __UNUSED__,
+                         Evas_Object *obj __UNUSED__,
+                         void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *vbox, *hbox, *ic, *bt, *fs_bt, *en, *lb;
+
+   win = elm_win_add(NULL, "fileselector button", ELM_WIN_BASIC);
+   elm_win_title_set(win, "File Selector Button");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   vbox = elm_box_add(win);
+   elm_win_resize_object_add(win, vbox);
+   evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(vbox);
+
+   /* file selector button */
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "file");
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   fs_bt = elm_fileselector_button_add(win);
+   elm_fileselector_button_label_set(fs_bt, "Select a file");
+   elm_fileselector_button_icon_set(fs_bt, ic);
+
+   elm_box_pack_end(vbox, fs_bt);
+   evas_object_show(fs_bt);
+   evas_object_show(ic);
+
+   /* attribute setting buttons */
+   hbox = elm_box_add(win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   elm_box_pack_end(vbox, hbox);
+   evas_object_show(hbox);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle current selection text entry");
+   evas_object_smart_callback_add(bt, "clicked", _current_sel_toggle, fs_bt);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle inwin mode");
+   evas_object_smart_callback_add(bt, "clicked", _inwin_mode_toggle, fs_bt);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle folder only mode");
+   evas_object_smart_callback_add(bt, "clicked", _folder_only_toggle, fs_bt);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle expandable mode");
+   evas_object_smart_callback_add(bt, "clicked", _expandable_toggle, fs_bt);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Last selection:");
+   elm_box_pack_end(vbox, lb);
+   evas_object_show(lb);
+
+   en = elm_entry_add(win);
+   elm_entry_line_wrap_set(en, EINA_FALSE);
+   elm_entry_editable_set(en, EINA_FALSE);
+   evas_object_smart_callback_add(fs_bt, "file,chosen", _file_chosen, en);
+   elm_box_pack_end(vbox, en);
+   evas_object_show(en);
+
+   evas_object_resize(win, 400, 400);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_fileselector_entry.c b/src/bin/test_fileselector_entry.c
new file mode 100644 (file)
index 0000000..0359dd5
--- /dev/null
@@ -0,0 +1,159 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+_file_chosen(void            *data,
+             Evas_Object *obj __UNUSED__,
+             void            *event_info)
+{
+   Evas_Object *entry = data;
+   char *file = event_info;
+   elm_entry_entry_set(entry, file);
+   printf("File chosen: %s\n", file);
+}
+
+static void
+_inwin_mode_toggle(void            *data,
+                   Evas_Object *obj __UNUSED__,
+                   void *event_info __UNUSED__)
+{
+   Evas_Object *fs_en = data;
+   Eina_Bool value = elm_fileselector_entry_inwin_mode_get(fs_en);
+   elm_fileselector_entry_inwin_mode_set(fs_en, !value);
+   printf("Inwin mode set to: %s\n", value ? "false" : "true");
+}
+
+static void
+_folder_only_toggle(void            *data,
+                    Evas_Object *obj __UNUSED__,
+                    void *event_info __UNUSED__)
+{
+   Evas_Object *fs_en = data;
+   Evas_Object *ic = elm_fileselector_entry_button_icon_get(fs_en);
+   Eina_Bool value = elm_fileselector_entry_folder_only_get(fs_en);
+   elm_fileselector_entry_folder_only_set(fs_en, !value);
+   printf("Folder only flag set to: %s\n", value ? "false" : "true");
+   if (!value)
+     {
+        elm_icon_standard_set(ic, "folder");
+        elm_fileselector_entry_button_label_set(fs_en, "Select a folder");
+     }
+   else
+     {
+        elm_icon_standard_set(ic, "file");
+        elm_fileselector_entry_button_label_set(fs_en, "Select a file");
+     }
+}
+
+static void
+_expandable_toggle(void            *data,
+                   Evas_Object *obj __UNUSED__,
+                   void *event_info __UNUSED__)
+{
+   Evas_Object *fs_en = data;
+   Eina_Bool value = elm_fileselector_entry_expandable_get(fs_en);
+   elm_fileselector_entry_expandable_set(fs_en, !value);
+   printf("Expandable flag set to: %s\n", value ? "false" : "true");
+}
+
+static void
+_disabled_toggle(void            *data,
+                 Evas_Object *obj __UNUSED__,
+                 void *event_info __UNUSED__)
+{
+   Evas_Object *fs_en = data;
+   Eina_Bool value = elm_object_disabled_get(fs_en);
+   elm_object_disabled_set(fs_en, !value);
+   printf("Disabled flag set to: %s\n", value ? "false" : "true");
+}
+
+void
+test_fileselector_entry(void *data       __UNUSED__,
+                        Evas_Object *obj __UNUSED__,
+                        void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *vbox, *hbox, *ic, *bt, *fs_en, *en, *lb;
+
+   win = elm_win_add(NULL, "fileselector entry", ELM_WIN_BASIC);
+   elm_win_title_set(win, "File Selector Entry");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   vbox = elm_box_add(win);
+   evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, vbox);
+   evas_object_show(vbox);
+
+   /* file selector entry */
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "file");
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   fs_en = elm_fileselector_entry_add(win);
+   elm_fileselector_entry_button_label_set(fs_en, "Select a file");
+   elm_fileselector_entry_button_icon_set(fs_en, ic);
+   evas_object_size_hint_weight_set(fs_en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(fs_en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   elm_box_pack_end(vbox, fs_en);
+   evas_object_show(fs_en);
+   evas_object_show(ic);
+
+   /* attribute setting buttons */
+   hbox = elm_box_add(win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   elm_box_pack_end(vbox, hbox);
+   evas_object_show(hbox);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle inwin mode");
+   evas_object_smart_callback_add(bt, "clicked", _inwin_mode_toggle, fs_en);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle folder only mode");
+   evas_object_smart_callback_add(bt, "clicked", _folder_only_toggle, fs_en);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle expandable mode");
+   evas_object_smart_callback_add(bt, "clicked", _expandable_toggle, fs_en);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Last selection:");
+   elm_box_pack_end(vbox, lb);
+   evas_object_show(lb);
+
+   hbox = elm_box_add(win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   elm_box_pack_end(vbox, hbox);
+   evas_object_show(hbox);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Toggle disabled");
+   evas_object_smart_callback_add(bt, "clicked", _disabled_toggle, fs_en);
+   elm_box_pack_end(hbox, bt);
+   evas_object_show(bt);
+
+   en = elm_entry_add(win);
+   elm_entry_line_wrap_set(en, EINA_FALSE);
+   elm_entry_editable_set(en, EINA_FALSE);
+   evas_object_smart_callback_add(fs_en, "file,chosen", _file_chosen, en);
+   elm_box_pack_end(vbox, en);
+   evas_object_show(en);
+
+   evas_object_resize(win, 400, 500);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_flip.c b/src/bin/test_flip.c
new file mode 100644 (file)
index 0000000..74f850f
--- /dev/null
@@ -0,0 +1,494 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+void
+my_fl_1(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_ROTATE_Y_CENTER_AXIS);
+}
+
+void
+my_fl_2(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_ROTATE_X_CENTER_AXIS);
+}
+
+void
+my_fl_3(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_ROTATE_XZ_CENTER_AXIS);
+}
+
+void
+my_fl_4(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_ROTATE_YZ_CENTER_AXIS);
+}
+
+void
+my_fl_5(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_CUBE_LEFT);
+}
+
+void
+my_fl_6(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_CUBE_RIGHT);
+}
+
+void
+my_fl_7(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_CUBE_UP);
+}
+
+void
+my_fl_8(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fl = data;
+   elm_flip_go(fl, ELM_FLIP_CUBE_DOWN);
+}
+
+void
+test_flip(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *fl, *o, *bt, *ly;
+   char buf[PATH_MAX];
+   
+   win = elm_win_add(NULL, "flip", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Flip");
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+   
+   fl = elm_flip_add(win);
+   evas_object_size_hint_align_set(fl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, fl);
+
+   o = elm_bg_add(win);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, "sky_01.jpg");
+   elm_bg_file_set(o, buf, NULL);
+   elm_flip_content_front_set(fl, o);
+   evas_object_show(o);
+   
+   ly = elm_layout_add(win);
+   snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+   elm_layout_file_set(ly, buf, "layout");
+   evas_object_size_hint_align_set(ly, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_flip_content_back_set(fl, ly);
+   evas_object_show(ly);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 1");
+   elm_layout_content_set(ly, "element1", bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 2");
+   elm_layout_content_set(ly, "element2", bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 3");
+   elm_layout_content_set(ly, "element3", bt);
+   evas_object_show(bt);
+
+   evas_object_show(fl);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "1");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_1, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "2");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_2, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "3");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_3, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "4");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_4, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+   
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "5");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_5, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "6");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_6, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "7");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_7, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "8");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_8, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+void
+test_flip2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *fl, *o, *bt, *tb, *li, *en;
+   char buf[PATH_MAX];
+   
+   win = elm_win_add(NULL, "flip2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Flip 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, "sky_01.jpg");
+   elm_bg_file_set(bg, buf, NULL);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+   
+   fl = elm_flip_add(win);
+   evas_object_size_hint_align_set(fl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, fl);
+
+   o = elm_box_add(win);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   
+   tb = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(tb, 0);
+   evas_object_size_hint_weight_set(tb, 0.0, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
+
+   elm_toolbar_item_append(tb, "arrow_left", "Hello", NULL, NULL);
+   elm_toolbar_item_append(tb, "arrow_right", "Out", NULL, NULL);
+   elm_toolbar_item_append(tb, "home", "There", NULL, NULL);
+   elm_toolbar_item_append(tb, "refresh", "World", NULL, NULL);
+   
+   elm_box_pack_end(o, tb);
+   evas_object_show(tb);
+   
+   li = elm_list_add(win);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   
+   elm_list_item_append(li, "This is a list", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Second item", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "3rd", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Fourth", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Number five is alive!", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "The quick brown fox jumps over the lazy dog", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Booyah", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "And another item", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "More of them", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Get with it", NULL, NULL,  NULL, NULL);
+   
+   elm_list_go(li);
+   
+   elm_box_pack_end(o, li);
+   evas_object_show(li);
+   
+   elm_flip_content_front_set(fl, o);
+   evas_object_show(o);
+
+   en = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_line_wrap_set(en, EINA_FALSE);
+   snprintf(buf, sizeof(buf),
+            "This is an entry widget in this window that<br>"
+            "uses markup <b>like this</> for styling and<br>"
+            "formatting <em>like this</>, as well as<br>"
+            "<a href=X><link>links in the text</></a>, so enter text<br>"
+            "in here to edit it. By the way, links are<br>"
+            "called <a href=anc-02>Anchors</a> so you will need<br>"
+            "to refer to them this way.<br>"
+            "<br>"
+            
+            "Also you can stick in items with (relsize + ascent): "
+            "<item relsize=16x16 vsize=ascent href=emoticon/evil-laugh></item>"
+            " (full) "
+            "<item relsize=16x16 vsize=full href=emoticon/guilty-smile></item>"
+            " (to the left)<br>"
+            
+            "Also (size + ascent): "
+            "<item size=16x16 vsize=ascent href=emoticon/haha></item>"
+            " (full) "
+            "<item size=16x16 vsize=full href=emoticon/happy-panting></item>"
+            " (before this)<br>"
+            
+            "And as well (absize + ascent): "
+            "<item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item>"
+            " (full) "
+            "<item absize=64x64 vsize=full href=emoticon/not-impressed></item>"
+            " or even paths to image files on disk too like: "
+            "<item absize=96x128 vsize=full href=file://%s/images/sky_01.jpg></item>"
+            " ... end."
+            , PACKAGE_DATA_DIR
+           );
+   elm_scrolled_entry_entry_set(en, buf);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   
+   elm_flip_content_back_set(fl, en);
+   evas_object_show(en);
+
+   evas_object_show(fl);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "1");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_1, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "2");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_2, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "3");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_3, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "4");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_4, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "5");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_5, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "6");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_6, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+   
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+void
+test_flip3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bx2, *fl, *fl_f, *fl_b, *o, *bt, *fr;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "flip flip", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Flip Flip");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   fl = elm_flip_add(win);
+   evas_object_size_hint_align_set(fl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, fl);
+   evas_object_show(fl);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Front");
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_flip_content_front_set(fl, fr);
+   evas_object_show(fr);
+   
+   fl_f = elm_flip_add(win);
+   evas_object_size_hint_align_set(fl_f, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fl_f, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_frame_content_set(fr, fl_f);
+   evas_object_show(fl_f);
+   
+   o = elm_bg_add(win);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, "sky_01.jpg");
+   elm_bg_file_set(o, buf, NULL);
+   elm_flip_content_front_set(fl_f, o);
+   evas_object_show(o);
+
+   o = elm_bg_add(win);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, "sky_02.jpg");
+   elm_bg_file_set(o, buf, NULL);
+   elm_flip_content_back_set(fl_f, o);
+   evas_object_show(o);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Back");
+   evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_flip_content_back_set(fl, fr);
+   evas_object_show(fr);
+   
+   fl_b = elm_flip_add(win);
+   evas_object_size_hint_align_set(fl_b, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fl_b, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_frame_content_set(fr, fl_b);
+   evas_object_show(fl_b);
+   
+   o = elm_bg_add(win);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, "sky_03.jpg");
+   elm_bg_file_set(o, buf, NULL);
+   elm_flip_content_front_set(fl_b, o);
+   evas_object_show(o);
+
+   o = elm_bg_add(win);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, "sky_04.jpg");
+   elm_bg_file_set(o, buf, NULL);
+   elm_flip_content_back_set(fl_b, o);
+   evas_object_show(o);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Main Flip");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_6, fl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Front Flip");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_6, fl_f);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Back Flip");
+   evas_object_smart_callback_add(bt, "clicked", my_fl_6, fl_b);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_flipselector.c b/src/bin/test_flipselector.c
new file mode 100644 (file)
index 0000000..5ab4cda
--- /dev/null
@@ -0,0 +1,115 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+void
+_sel_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Flipselector_Item *it;
+
+   it = event_info;
+   printf("label of selected item is: %s\n", elm_flipselector_item_label_get(it));
+}
+
+void
+_unsel_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Flipselector_Item *it;
+   Evas_Object *fp = data;
+   it = elm_flipselector_selected_item_get(fp);
+   elm_flipselector_item_selected_set(it, EINA_FALSE);
+}
+
+void
+_third_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Flipselector_Item *it;
+   Evas_Object *fp = data;
+   it = elm_flipselector_first_item_get(fp);
+   it = elm_flipselector_item_next_get(it);
+   it = elm_flipselector_item_next_get(it);
+   elm_flipselector_item_selected_set(it, EINA_TRUE);
+}
+
+void
+_underflow_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("underflow!\n");
+}
+
+void
+_overflow_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("overflow!\n");
+}
+
+void
+test_flipselector(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   char buf[8];
+   unsigned int i;
+   Evas_Object *win, *bg, *bx, *fp, *bt;
+   static const char *lbl[] = {
+     "Elementary",
+     "Evas",
+     "Eina",
+     "Edje",
+     "Eet",
+     "Ecore",
+     "Efreet",
+     "Edbus"
+   };
+
+   win = elm_win_add(NULL, "flipselector", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Flip Selector");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   fp = elm_flipselector_add(win);
+   evas_object_size_hint_weight_set(fp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_smart_callback_add(fp, "selected", _sel_cb, NULL);
+   evas_object_smart_callback_add(fp, "underflowed", _overflow_cb, NULL);
+   evas_object_smart_callback_add(fp, "overflowed", _underflow_cb, NULL);
+   for (i = 0; i < sizeof(lbl)/sizeof(char *); i++)
+     elm_flipselector_item_append(fp, lbl[i], NULL, NULL);
+   elm_box_pack_end(bx, fp);
+   evas_object_show(fp);
+
+   fp = elm_flipselector_add(win);
+   evas_object_smart_callback_add(fp, "underflowed", _overflow_cb, NULL);
+   evas_object_smart_callback_add(fp, "overflowed", _underflow_cb, NULL);
+   evas_object_size_hint_weight_set(fp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   for (i = 1990; i < 2099; i++)
+     {
+       snprintf(buf, 8, "%d", i);
+       elm_flipselector_item_append(fp, buf, _sel_cb, NULL);
+     }
+   elm_box_pack_end(bx, fp);
+   evas_object_show(fp);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Select 1992");
+   evas_object_smart_callback_add(bt, "clicked", _third_cb, fp);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Unselect year");
+   evas_object_smart_callback_add(bt, "clicked", _unsel_cb, fp);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_floating.c b/src/bin/test_floating.c
new file mode 100644 (file)
index 0000000..96764d6
--- /dev/null
@@ -0,0 +1,109 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+typedef struct _Testitem
+{
+   Elm_Genlist_Item *item;
+   int mode;
+   int onoff;
+} Testitem;
+
+
+static Elm_Genlist_Item_Class itc1;
+static char *glf_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item # %i", (int)(long)data);
+   return strdup(buf);
+}
+
+static Evas_Object *glf_icon_get(void *data __UNUSED__, Evas_Object *obj, const char *part __UNUSED__)
+{
+   char buf[PATH_MAX];
+   Evas_Object *ic = elm_icon_add(obj);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   return ic;
+}
+static Eina_Bool glf_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   return EINA_FALSE;
+}
+static void glf_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+static void
+gl_sel(void *data, Evas_Object *obj, void *event_info)
+{
+   printf("sel item data [%p] on genlist obj [%p], item pointer [%p]\n", data, obj, event_info);
+}
+
+static Eina_Bool
+anim(void *data)
+{
+   Evas_Object *gl = data;
+   Evas_Coord x, y;
+   
+   y = 0;
+   x = (sin(ecore_loop_time_get()) * 500);
+   evas_object_move(gl, x, y);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Animator *ani = data;
+   
+   ecore_animator_del(ani);
+}
+
+void
+test_floating(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl;
+   int i;
+   Ecore_Animator *ani;
+
+   win = elm_win_add(NULL, "floating", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Floaating");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_move(gl, 800, 0);
+   evas_object_resize(gl, 480, 800);
+   evas_object_show(gl);
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = glf_label_get;
+   itc1.func.icon_get  = glf_icon_get;
+   itc1.func.state_get = glf_state_get;
+   itc1.func.del       = glf_del;
+
+   for (i = 0; i < 20; i++)
+     {
+        elm_genlist_item_append(gl, &itc1,
+                                (void *)(long)i/* item data */,
+                                NULL/* parent */,
+                                ELM_GENLIST_ITEM_NONE,
+                                gl_sel/* func */,
+                                (void *)(long)(i * 10)/* func data */);
+     }
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+   
+   ani = ecore_animator_add(anim, gl);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _del, ani);
+}
+#endif
diff --git a/src/bin/test_focus.c b/src/bin/test_focus.c
new file mode 100644 (file)
index 0000000..7227d6d
--- /dev/null
@@ -0,0 +1,376 @@
+/* Test for Focus Chain Linear*/
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static Eina_Bool
+_event(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type == EVAS_CALLBACK_KEY_DOWN)
+     printf ("Key Down:");
+   else if (type == EVAS_CALLBACK_KEY_UP)
+     printf ("Key Up:");
+   else
+     return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   printf("%s\n", ev->key);
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+}
+
+static void
+_on_key_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *einfo __UNUSED__)
+{
+   //Evas_Event_Key_Down *event = einfo;
+   //printf("%s %p Key %s Parent %p\n", evas_object_type_get(obj),
+   //       obj, event->keyname, evas_object_smart_parent_get(obj));
+}
+
+static void
+_disable(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *bt = data;
+   elm_object_disabled_set(bt, EINA_TRUE);
+}
+
+static void
+_enable(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *bt = data;
+   elm_object_disabled_set(bt, EINA_FALSE);
+}
+
+static inline void
+my_show(Evas_Object *obj)
+{
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
+                                  _on_key_down, NULL);
+   evas_object_show(obj);
+}
+
+void
+test_focus(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win;
+   unsigned int i, j;
+
+   win = elm_win_add(NULL, "focus", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Focus");
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+   evas_object_resize(win, 800, 600);
+   elm_object_event_callback_add(win, _event, NULL);
+   elm_win_autodel_set(win, EINA_TRUE);
+   my_show(win);
+
+     {
+        Evas_Object *bg;
+        bg = elm_bg_add(win);
+        evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+        elm_win_resize_object_add(win, bg);
+        my_show(bg);
+     }
+
+   Evas_Object *mainbx = elm_box_add(win);
+   elm_box_horizontal_set(mainbx, EINA_TRUE);
+   elm_win_resize_object_add(win, mainbx);
+   evas_object_size_hint_weight_set(mainbx, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   my_show(mainbx);
+
+     { //First Col
+        Evas_Object *bx = elm_box_add(win);
+        evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+        elm_box_pack_end(mainbx, bx);
+        my_show(bx);
+
+          {
+             Evas_Object *lb = elm_label_add(win);
+             elm_label_label_set(lb,
+                                 "<b>Use Tab and Shift+Tab</b>"
+                                );
+             evas_object_size_hint_weight_set(lb, 0.0, 0.0);
+             evas_object_size_hint_align_set(lb, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+             elm_box_pack_end(bx, lb);
+             my_show(lb);
+          }
+
+          {
+             Evas_Object *tg = elm_toggle_add(win);
+             elm_toggle_states_labels_set(tg, "Yes", "No");
+             elm_box_pack_end(bx, tg);
+             my_show(tg);
+          }
+
+          {
+             Evas_Object *en = elm_scrolled_entry_add(win);
+             evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+             evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+             elm_scrolled_entry_entry_set(en, "This is a single line");
+             elm_scrolled_entry_single_line_set(en, 1);
+             elm_box_pack_end(bx, en);
+             my_show(en);
+          }
+
+          {
+             Evas_Object *bx2 = elm_box_add(win);
+             elm_box_horizontal_set(bx2, EINA_TRUE);
+             evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+             evas_object_size_hint_weight_set(bx2, 0.0, 0.0);
+             elm_box_pack_end(bx, bx2);
+
+             for (i = 2; i; i--)
+               {
+                  Evas_Object *bt;
+                  bt = elm_button_add(win);
+                  elm_button_label_set(bt, "Box");
+                  evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+                  if (i%2)
+                    elm_object_disabled_set(bt, EINA_TRUE);
+                  elm_box_pack_end(bx2, bt);
+                  my_show(bt);
+               }
+
+               {
+                  Evas_Object *sc = elm_scroller_add(win);
+                  evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND,
+                                                   EVAS_HINT_EXPAND);
+                  evas_object_size_hint_align_set(sc, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  elm_scroller_bounce_set(sc, 1, 1);
+                  elm_scroller_content_min_limit(sc, 1, 1);
+                  elm_box_pack_end(bx2, sc);
+                  my_show(sc);
+
+                    {
+                       Evas_Object *bt;
+                       bt = elm_button_add(win);
+                       elm_button_label_set(bt, "Scroller");
+                       evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                       EVAS_HINT_FILL);
+                       evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+                       elm_object_event_callback_add(bt, _event, NULL);
+                       elm_scroller_content_set(sc, bt);
+                       my_show(bt);
+                       elm_object_event_callback_del(bt, _event, NULL);
+                    }
+               }
+
+             my_show(bx2);
+          }
+
+          {
+             Evas_Object *bt;
+             bt = elm_button_add(win);
+             elm_button_label_set(bt, "Box");
+             evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+             evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+             elm_box_pack_end(bx, bt);
+             my_show(bt);
+          }
+
+          {
+             Evas_Object *bx2 = elm_box_add(win);
+             elm_box_horizontal_set(bx2, EINA_TRUE);
+             evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+             evas_object_size_hint_weight_set(bx2, 0.0, 0.0);
+             elm_box_pack_end(bx, bx2);
+             my_show(bx2);
+
+             for (i = 2; i; i--)
+               {
+                  Evas_Object *bx3 = elm_box_add(win);
+                  evas_object_size_hint_align_set(bx3, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  evas_object_size_hint_weight_set(bx3, 0.0, 0.0);
+                  elm_box_pack_end(bx2, bx3);
+                  my_show(bx3);
+
+                  for (j = 3; j; j--)
+                    {
+                       Evas_Object *bt;
+                       bt = elm_button_add(win);
+                       elm_button_label_set(bt, "Box");
+                       evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                       EVAS_HINT_FILL);
+                       evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+                       elm_box_pack_end(bx3, bt);
+                       my_show(bt);
+                    }
+               }
+
+               {
+                  Evas_Object *sc = elm_scroller_add(win);
+                  evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND,
+                                                   EVAS_HINT_EXPAND);
+                  evas_object_size_hint_align_set(sc, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  elm_scroller_bounce_set(sc, 0, 1);
+                  elm_scroller_content_min_limit(sc, 1, 0);
+                  elm_box_pack_end(bx2, sc);
+                  my_show(sc);
+
+                  Evas_Object *bx3 = elm_box_add(win);
+                  evas_object_size_hint_align_set(bx3, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  evas_object_size_hint_weight_set(bx3, 0.0, 0.0);
+                  elm_scroller_content_set(sc, bx3);
+                  my_show(bx3);
+
+                  for (i = 5; i; i--)
+                    {
+                       Evas_Object *bt;
+                       bt = elm_button_add(win);
+                       elm_button_label_set(bt, "BX Scroller");
+                       evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                       EVAS_HINT_FILL);
+                       evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+                       elm_box_pack_end(bx3, bt);
+                       my_show(bt);
+                    }
+               }
+          }
+     }
+
+     {//Second Col
+        char buf[PATH_MAX];
+        Evas_Object *ly = elm_layout_add(win);
+        snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+        elm_layout_file_set(ly, buf, "twolines");
+        evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+        elm_box_pack_end(mainbx, ly);
+        my_show(ly);
+
+          {
+             Evas_Object *bx2 = elm_box_add(win);
+             elm_box_horizontal_set(bx2, EINA_TRUE);
+             evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+             evas_object_size_hint_weight_set(bx2, 0.0, 0.0);
+             elm_layout_content_set(ly, "element1", bx2);
+             my_show(bx2);
+
+             for (i = 3; i; i--)
+               {
+                  Evas_Object *bt;
+                  bt = elm_button_add(win);
+                  elm_button_label_set(bt, "Layout");
+                  evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+                  elm_box_pack_end(bx2, bt);
+                  my_show(bt);
+                  elm_object_focus_custom_chain_prepend(bx2, bt, NULL);
+               }
+          }
+
+          {
+             Evas_Object *bx2 = elm_box_add(win);
+             evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+             evas_object_size_hint_weight_set(bx2, 0.0, 0.0);
+             elm_layout_content_set(ly, "element2", bx2);
+             my_show(bx2);
+
+               {
+                  Evas_Object *bt;
+                  bt = elm_button_add(win);
+                  elm_button_label_set(bt, "Disable");
+                  evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+                  elm_box_pack_end(bx2, bt);
+                  evas_object_smart_callback_add(bt, "clicked", _disable, bt);
+                  my_show(bt);
+                  elm_object_focus_custom_chain_prepend(bx2, bt, NULL);
+
+                  Evas_Object *bt2;
+                  bt2 = elm_button_add(win);
+                  elm_button_label_set(bt2, "Enable");
+                  evas_object_size_hint_align_set(bt2, EVAS_HINT_FILL,
+                                                  EVAS_HINT_FILL);
+                  evas_object_size_hint_weight_set(bt2, 0.0, 0.0);
+                  elm_box_pack_end(bx2, bt2);
+                  evas_object_smart_callback_add(bt2, "clicked", _enable, bt);
+                  my_show(bt2);
+                  elm_object_focus_custom_chain_append(bx2, bt2, NULL);
+               }
+
+          }
+     }
+
+     {//Third Col
+        Evas_Object *bx = elm_box_add(win);
+        evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND,
+                                         EVAS_HINT_EXPAND);
+        elm_box_pack_end(mainbx, bx);
+        my_show(bx);
+
+          {
+             Evas_Object *fr = elm_frame_add(win);
+             elm_frame_label_set(fr, "Frame");
+             elm_box_pack_end(bx, fr);
+             evas_object_show(fr);
+
+               {
+                  Evas_Object *tb = elm_table_add(win);
+                  evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                  elm_frame_content_set(fr, tb);
+                  my_show(tb);
+                  for (j = 0; j < 1; j++)
+                    for (i = 0; i < 2; i++)
+                      {
+                         Evas_Object *bt;
+                         bt = elm_button_add(win);
+                         elm_button_label_set(bt, "Table");
+                         evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                         EVAS_HINT_FILL);
+                         evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                         elm_table_pack(tb, bt, i, j, 1, 1);
+                         my_show(bt);
+                      }
+               }
+          }
+
+          {
+             Evas_Object *fr = elm_bubble_add(win);
+             elm_bubble_label_set(fr, "Bubble");
+             evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             evas_object_size_hint_align_set(fr, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+             elm_box_pack_end(bx, fr);
+             evas_object_show(fr);
+
+               {
+                  Evas_Object *tb = elm_table_add(win);
+                  evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                  elm_bubble_content_set(fr, tb);
+                  my_show(tb);
+                  for (j = 0; j < 2; j++)
+                    for (i = 0; i < 1; i++)
+                      {
+                         Evas_Object *bt;
+                         bt = elm_button_add(win);
+                         elm_button_label_set(bt, "Table");
+                         evas_object_size_hint_align_set(bt, EVAS_HINT_FILL,
+                                                         EVAS_HINT_FILL);
+                         evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                         elm_table_pack(tb, bt, i, j, 1, 1);
+                         my_show(bt);
+                      }
+               }
+          }
+     }
+}
+#endif
diff --git a/src/bin/test_focus2.c b/src/bin/test_focus2.c
new file mode 100644 (file)
index 0000000..5191a26
--- /dev/null
@@ -0,0 +1,151 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+_focus_in(void *data __UNUSED__, Evas *e __UNUSED__, void *event_info)
+{
+   const char *type = evas_object_type_get(event_info);
+   if ((type) && (!strcmp(type, "elm_widget")))
+     type = elm_object_widget_type_get(event_info);
+   printf("Evas_Object focus in: %p %s\n", event_info, type);
+}
+
+static void
+_focus_out(void *data __UNUSED__, Evas *e __UNUSED__, void *event_info)
+{
+   const char *type = evas_object_type_get(event_info);
+   if ((type) && (!strcmp(type, "elm_widget")))
+     type = elm_object_widget_type_get(event_info);
+   printf("Evas_Object focus out: %p %s\n", event_info, type);
+}
+
+static void
+_focus_obj(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *newfocus = data;
+   const char *type = evas_object_type_get(newfocus);
+   if ((type) && (!strcmp(type, "elm_widget")))
+     type = elm_object_widget_type_get(newfocus);
+   printf("elm_object_focus(%p) %s\n", newfocus, type);
+   elm_object_focus(newfocus);
+}
+
+static void
+_focus_layout_part(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *ed = elm_layout_edje_get(data);
+
+   Evas_Object *newfocus = (Evas_Object *)edje_object_part_object_get(ed, "sky");
+   const char *type = evas_object_type_get(newfocus);
+   printf("evas_object_focus_set(%p, 1) %s\n", newfocus, type);
+   evas_object_focus_set(newfocus, EINA_TRUE);;
+}
+
+
+void
+test_focus2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ly, *bt, *en, *bt1;
+
+   win = elm_win_add(NULL, "focus2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Focus2");
+   elm_win_autodel_set(win, 1);
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+
+   evas_event_callback_add
+     (evas_object_evas_get(win), EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+      _focus_in, NULL);
+   evas_event_callback_add
+     (evas_object_evas_get(win), EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
+      _focus_out, NULL);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+#define PARENT bx /* this is broken, but should work */
+//#define PARENT win
+
+   en = elm_scrolled_entry_add(PARENT);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_entry_set(en, "Scrolled Entry that should get focus");
+   elm_scrolled_entry_single_line_set(en, 1);
+   evas_object_show(en);
+   elm_box_pack_end(bx, en);
+
+   bt = elm_button_add(PARENT);
+   elm_button_label_set(bt, "Give focus to scrolled entry");
+   evas_object_smart_callback_add(bt, "clicked", _focus_obj, en);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   ly = elm_layout_add(PARENT);
+   elm_layout_file_set(ly, PACKAGE_DATA_DIR"/objects/test.edj", "layout");
+   evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, ly);
+   evas_object_show(ly);
+
+   bt1 = bt = elm_button_add(ly);
+   elm_button_label_set(bt, "Button 1");
+   elm_layout_content_set(ly, "element1", bt);
+
+   en = elm_scrolled_entry_add(ly);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_entry_set(en, "Scrolled Entry that should get focus");
+   elm_scrolled_entry_single_line_set(en, 1);
+   elm_layout_content_set(ly, "element2", en);
+
+   bt = elm_button_add(ly);
+   elm_button_label_set(bt, "Button 2");
+   elm_layout_content_set(ly, "element3", bt);
+
+   bt = elm_button_add(PARENT);
+   elm_button_label_set(bt, "Give focus to layout");
+   evas_object_smart_callback_add(bt, "clicked", _focus_obj, ly);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(PARENT);
+   elm_button_label_set(bt, "Give focus to layout part");
+   evas_object_smart_callback_add(bt, "clicked", _focus_layout_part, ly);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(PARENT);
+   elm_button_label_set(bt, "Give focus to layout 'Button 1'");
+   evas_object_smart_callback_add(bt, "clicked", _focus_obj, bt1);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(PARENT);
+   elm_button_label_set(bt, "Give focus to layout 'Entry'");
+   evas_object_smart_callback_add(bt, "clicked", _focus_obj, en);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   evas_object_resize(win, 400, 400);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_gengrid.c b/src/bin/test_gengrid.c
new file mode 100644 (file)
index 0000000..f5c6b14
--- /dev/null
@@ -0,0 +1,357 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+typedef struct _Testitem
+{
+   Elm_Gengrid_Item *item;
+   const char *path;
+   int mode;
+   int onoff;
+} Testitem;
+
+static const char *img[9] =
+{
+   "panel_01.jpg",
+   "plant_01.jpg",
+   "rock_01.jpg",
+   "rock_02.jpg",
+   "sky_01.jpg",
+   "sky_02.jpg",
+   "sky_03.jpg",
+   "sky_04.jpg",
+   "wood_01.jpg",
+};
+
+static Elm_Gengrid_Item_Class gic;
+
+static void
+_horizontal_grid(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *grid = data;
+   elm_gengrid_horizontal_set(grid, elm_check_state_get(obj));
+}
+
+static void
+grid_drag_up(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("Drag up: %p\n", event_info);
+}
+
+static void
+grid_drag_right(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("Drag right: %p\n", event_info);
+}
+
+static void
+grid_drag_down(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("Drag down: %p\n", event_info);
+}
+
+static void
+grid_drag_left(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("Drag left: %p\n", event_info);
+}
+
+static void
+grid_drag_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("Drag stop: %p\n", event_info);
+}
+
+static void
+grid_selected(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("Selected: %p\n", event_info);
+}
+
+static void
+grid_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("Clicked: %p\n", event_info);
+}
+
+static void
+grid_longpress(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("longpress %p\n", event_info);
+}
+
+static void
+grid_item_check_changed(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Testitem *ti = data;
+   ti->onoff = elm_check_state_get(obj);
+   printf("item %p onoff = %i\n", ti, ti->onoff);
+}
+
+char *
+grid_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   const Testitem *ti = data;
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Photo %s", ti->path);
+   return strdup(buf);
+}
+
+Evas_Object *
+grid_icon_get(void *data, Evas_Object *obj, const char *part)
+{
+   const Testitem *ti = data;
+   if (!strcmp(part, "elm.swallow.icon"))
+     {
+
+       Evas_Object *icon = elm_bg_add(obj);
+       elm_bg_file_set(icon, ti->path, NULL);
+       evas_object_size_hint_aspect_set(icon, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+       evas_object_show(icon);
+       return icon;
+     }
+   else if (!strcmp(part, "elm.swallow.end"))
+     {
+       Evas_Object *ck;
+       ck = elm_check_add(obj);
+       evas_object_propagate_events_set(ck, 0);
+       elm_check_state_set(ck, ti->onoff);
+       evas_object_smart_callback_add(ck, "changed", grid_item_check_changed, data);
+       evas_object_show(ck);
+       return ck;
+     }
+   return NULL;
+}
+
+Eina_Bool
+grid_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   return EINA_FALSE;
+}
+
+void
+grid_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+static void
+grid_sel(void *data, Evas_Object *obj, void *event_info)
+{
+   printf("sel item data [%p] on grid obj [%p], pointer [%p]\n", data, obj, event_info);
+}
+
+void
+test_gengrid(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *grid;
+   static Testitem ti[144];
+   int i, n;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "grid", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Grid");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   grid = elm_gengrid_add(win);
+   elm_gengrid_item_size_set(grid, 150, 150);
+   elm_gengrid_horizontal_set(grid, EINA_FALSE);
+   elm_gengrid_multi_select_set(grid, EINA_TRUE);
+   evas_object_smart_callback_add(grid, "selected", grid_selected, NULL);
+   evas_object_smart_callback_add(grid, "clicked", grid_clicked, NULL);
+   evas_object_smart_callback_add(grid, "longpressed", grid_longpress, NULL);
+   evas_object_smart_callback_add(grid, "drag,start,up", grid_drag_up, NULL);
+   evas_object_smart_callback_add(grid, "drag,start,right", grid_drag_right, NULL);
+   evas_object_smart_callback_add(grid, "drag,start,down", grid_drag_down, NULL);
+   evas_object_smart_callback_add(grid, "drag,start,left", grid_drag_left, NULL);
+   evas_object_smart_callback_add(grid, "drag,stop", grid_drag_stop, NULL);
+   evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   gic.item_style = "default";
+   gic.func.label_get = grid_label_get;
+   gic.func.icon_get = grid_icon_get;
+   gic.func.state_get = grid_state_get;
+   gic.func.del = grid_del;
+
+   n = 0;
+   for (i = 0; i < 12 * 12; i++)
+     {
+       snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, img[n]);
+       n = (n + 1) % 9;
+       ti[i].mode = i;
+       ti[i].path = eina_stringshare_add(buf);
+       ti[i].item = elm_gengrid_item_append(grid, &gic, &(ti[i]), grid_sel, NULL);
+       if (!(i % 5))
+         elm_gengrid_item_selected_set(ti[i].item, EINA_TRUE);
+     }
+
+   evas_object_show(grid);
+   elm_win_resize_object_add(win, grid);
+
+   evas_object_resize(win, 600, 600);
+   evas_object_show(win);
+}
+
+static void
+_before_bt_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Testitem *ti;
+   Evas_Object *grid = data;
+   Elm_Gengrid_Item *sel;
+   char buf[PATH_MAX];
+
+   sel = elm_gengrid_selected_item_get(grid);
+   if (!sel)
+       return;
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, img[rand() % 9]);
+   ti = malloc(sizeof(*ti));
+   ti->mode = 0;
+   ti->path = eina_stringshare_add(buf);
+   ti->item = elm_gengrid_item_insert_before(grid, &gic, ti, sel, grid_sel,
+                                             NULL);
+}
+
+static void
+_after_bt_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Testitem *ti;
+   Evas_Object *grid = data;
+   Elm_Gengrid_Item *sel;
+   char buf[PATH_MAX];
+
+   sel = elm_gengrid_selected_item_get(grid);
+   if (!sel)
+       return;
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, img[rand() % 9]);
+   ti = malloc(sizeof(*ti));
+   ti->mode = 0;
+   ti->path = eina_stringshare_add(buf);
+   ti->item = elm_gengrid_item_insert_after(grid, &gic, ti, sel, grid_sel,
+                                            NULL);
+}
+
+static void
+_prepend_bt_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Testitem *ti;
+   Evas_Object *grid = data;
+   char buf[PATH_MAX];
+
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, img[rand() % 9]);
+   ti = malloc(sizeof(*ti));
+   ti->mode = 0;
+   ti->path = eina_stringshare_add(buf);
+   ti->item = elm_gengrid_item_prepend(grid, &gic, ti, grid_sel, NULL);
+}
+
+static void
+_append_bt_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Testitem *ti;
+   Evas_Object *grid = data;
+   char buf[PATH_MAX];
+
+   snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR, img[rand() % 9]);
+   ti = malloc(sizeof(*ti));
+   ti->mode = 0;
+   ti->path = eina_stringshare_add(buf);
+   ti->item = elm_gengrid_item_append(grid, &gic, ti, grid_sel, NULL);
+}
+
+static void
+_size_changed(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *grid = data;
+   int size = elm_spinner_value_get(obj);
+   elm_gengrid_item_size_set(grid, size, size);
+}
+
+void
+test_gengrid2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *grid, *bx, *hbx, *bt, *ck;
+
+   win = elm_win_add(NULL, "grid2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Grid2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   grid = elm_gengrid_add(win);
+   elm_gengrid_item_size_set(grid, 150, 150);
+   elm_gengrid_horizontal_set(grid, EINA_FALSE);
+   elm_gengrid_multi_select_set(grid, EINA_FALSE);
+   evas_object_smart_callback_add(grid, "selected", grid_selected, NULL);
+   evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_min_set(grid, 600, 500);
+   elm_box_pack_end(bx, grid);
+   evas_object_show(grid);
+
+   hbx = elm_box_add(win);
+   evas_object_size_hint_weight_set(hbx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_horizontal_set(hbx, EINA_TRUE);
+   elm_box_pack_end(bx, hbx);
+   evas_object_show(hbx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Append");
+   evas_object_smart_callback_add(bt, "clicked", _append_bt_clicked, grid);
+   elm_box_pack_end(hbx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Prepend");
+   evas_object_smart_callback_add(bt, "clicked", _prepend_bt_clicked, grid);
+   elm_box_pack_end(hbx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Insert before");
+   evas_object_smart_callback_add(bt, "clicked", _before_bt_clicked, grid);
+   elm_box_pack_end(hbx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Insert after");
+   evas_object_smart_callback_add(bt, "clicked", _after_bt_clicked, grid);
+   elm_box_pack_end(hbx, bt);
+   evas_object_show(bt);
+
+   bt = elm_spinner_add(win);
+   elm_spinner_min_max_set(bt, 10, 1024);
+   elm_spinner_value_set(bt, 150);
+   elm_spinner_label_format_set(bt, "Item size: %.0f");
+   evas_object_smart_callback_add(bt, "changed", _size_changed, grid);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(hbx, bt);
+   evas_object_show(bt);
+
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Horizontal Mode");
+   evas_object_smart_callback_add(ck, "changed", _horizontal_grid, grid);
+   elm_box_pack_end(hbx, ck);
+   evas_object_show(ck);
+
+   gic.item_style = "default";
+   gic.func.label_get = grid_label_get;
+   gic.func.icon_get = grid_icon_get;
+   gic.func.state_get = grid_state_get;
+   gic.func.del = grid_del;
+
+   evas_object_resize(win, 600, 600);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_genlist.c b/src/bin/test_genlist.c
new file mode 100644 (file)
index 0000000..4f95890
--- /dev/null
@@ -0,0 +1,1631 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+/* Hint:
+ * In this example some calls to elm_genlist_item_append() are used which give the 
+ * value of an int as 'item data' and 'func data' after casting into (void*). For 
+ * sure this works only on architectures where sizeof(int)==sizeof(void*).
+ * For real world usage you should hold a data structure or value in your 
+ * application and then give only a pointer to this data as data pointer.
+ */
+
+typedef struct _Testitem
+{
+   Elm_Genlist_Item *item;
+   int mode;
+   int onoff;
+} Testitem;
+
+
+static Elm_Genlist_Item_Class itc1;
+char *gl_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item # %i", (int)(long)data);
+   return strdup(buf);
+}
+
+Evas_Object *gl_icon_get(void *data __UNUSED__, Evas_Object *obj, const char *part)
+{
+   char buf[PATH_MAX];
+   Evas_Object *ic = elm_icon_add(obj);
+   if (!strcmp(part, "elm.swallow.end"))
+      snprintf(buf, sizeof(buf), "%s/images/bubble.png", PACKAGE_DATA_DIR);
+   else
+      snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   return ic;
+}
+Eina_Bool gl_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   return EINA_FALSE;
+}
+void gl_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+static void
+gl_sel(void *data, Evas_Object *obj, void *event_info)
+{
+   printf("sel item data [%p] on genlist obj [%p], item pointer [%p]\n", data, obj, event_info);
+}
+
+static void
+_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Object *gl = data;
+   Evas_Event_Mouse_Move *ev = event_info;
+   int where = 0;
+   Elm_Genlist_Item *gli;
+   gli = elm_genlist_at_xy_item_get(gl, ev->cur.canvas.x, ev->cur.canvas.y, &where);
+   if (gli)
+     printf("over %p, where %i\n", elm_genlist_item_data_get(gli), where);
+   else
+     printf("over none, where %i\n", where);
+}
+
+static void
+_bt50_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    elm_genlist_item_bring_in(data);
+}
+
+static void
+_bt1500_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    elm_genlist_item_middle_bring_in(data);
+}
+
+static void
+_gl_selected(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("selected: %p\n", event_info);
+}
+
+static void
+_gl_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("clicked: %p\n", event_info);
+}
+
+static void
+_gl_longpress(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("longpress %p\n", event_info);
+}
+
+void
+test_genlist(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bt_50, *bt_1500, *bx;
+   Evas_Object *over;
+   Elm_Genlist_Item *gli;
+   int i;
+
+   win = elm_win_add(NULL, "genlist", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   evas_object_smart_callback_add(gl, "selected", _gl_selected, NULL);
+   evas_object_smart_callback_add(gl, "clicked", _gl_clicked, NULL);
+   evas_object_smart_callback_add(gl, "longpressed", _gl_longpress, NULL);
+   // FIXME: This causes genlist to resize the horiz axis very slowly :(
+   // Reenable this and resize the window horizontally, then try to resize it back
+   //elm_genlist_horizontal_mode_set(gl, ELM_LIST_LIMIT);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, gl);
+   evas_object_show(gl);
+
+   over = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_color_set(over, 0, 0, 0, 0);
+   evas_object_event_callback_add(over, EVAS_CALLBACK_MOUSE_MOVE, _move, gl);
+   evas_object_repeat_events_set(over, 1);
+   evas_object_show(over);
+   evas_object_size_hint_weight_set(over, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, over);
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = gl_label_get;
+   itc1.func.icon_get  = gl_icon_get;
+   itc1.func.state_get = gl_state_get;
+   itc1.func.del       = gl_del;
+
+   bt_50 = elm_button_add(win);
+   elm_button_label_set(bt_50, "Go to 50");
+   evas_object_show(bt_50);
+   elm_box_pack_end(bx, bt_50);
+
+   bt_1500 = elm_button_add(win);
+   elm_button_label_set(bt_1500, "Go to 1500");
+   evas_object_show(bt_1500);
+   elm_box_pack_end(bx, bt_1500);
+
+   for (i = 0; i < 2000; i++)
+     {
+        gli = elm_genlist_item_append(gl, &itc1,
+                                      (void *)(long)i/* item data */,
+                                      NULL/* parent */,
+                                      ELM_GENLIST_ITEM_NONE,
+                                      gl_sel/* func */,
+                                      (void *)(long)(i * 10)/* func data */);
+        if (i == 50)
+          evas_object_smart_callback_add(bt_50, "clicked", _bt50_cb, gli);
+        else if (i == 1500)
+          evas_object_smart_callback_add(bt_1500, "clicked", _bt1500_cb, gli);
+     }
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+}
+
+/*************/
+
+static void
+my_gl_clear(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   elm_genlist_clear(gl);
+}
+
+static void
+my_gl_add(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   static int i = 0;
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = gl_label_get;
+   itc1.func.icon_get  = gl_icon_get;
+   itc1.func.state_get = gl_state_get;
+   itc1.func.del       = gl_del;
+
+   elm_genlist_item_append(gl, &itc1,
+                           (void *)(long)i/* item data */,
+                           NULL/* parent */,
+                           ELM_GENLIST_ITEM_NONE,
+                           gl_sel/* func */,
+                           (void *)(long)(i * 10)/* func data */);
+   i++;
+}
+
+static void
+my_gl_insert_before(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   static int i = 0;
+   Elm_Genlist_Item *gli_selected;
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = gl_label_get;
+   itc1.func.icon_get  = gl_icon_get;
+   itc1.func.state_get = gl_state_get;
+   itc1.func.del       = gl_del;
+
+   gli_selected = elm_genlist_selected_item_get(gl);
+   if(!gli_selected)
+   {
+       printf("no item selected\n");
+       return ;
+   }
+
+   elm_genlist_item_insert_before(gl, &itc1,
+                                  (void *)(long)i/* item data */,
+                                  NULL/* parent */,
+                                  gli_selected /* item before */,
+                                  ELM_GENLIST_ITEM_NONE,
+                                  gl_sel/* func */,
+                                  (void *)(long)(i * 10)/* func data */);
+   i++;
+}
+
+static void
+my_gl_insert_after(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   static int i = 0;
+   Elm_Genlist_Item *gli_selected;
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = gl_label_get;
+   itc1.func.icon_get  = gl_icon_get;
+   itc1.func.state_get = gl_state_get;
+   itc1.func.del       = gl_del;
+
+   gli_selected = elm_genlist_selected_item_get(gl);
+   if(!gli_selected)
+   {
+       printf("no item selected\n");
+       return ;
+   }
+
+   elm_genlist_item_insert_after(gl, &itc1,
+                                 (void *)(long)i/* item data */,
+                                 NULL/* parent */,
+                                 gli_selected /* item after */,
+                                 ELM_GENLIST_ITEM_NONE,
+                                gl_sel/* func */,
+                                (void *)(long)(i * 10)/* func data */);
+   i++;
+}
+
+static void
+my_gl_del(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   Elm_Genlist_Item *gli = elm_genlist_selected_item_get(gl);
+   if (!gli)
+     {
+       printf("no item selected\n");
+       return;
+     }
+   elm_genlist_item_del(gli);
+}
+
+static void
+my_gl_disable(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   Elm_Genlist_Item *gli = elm_genlist_selected_item_get(gl);
+   if (!gli)
+     {
+       printf("no item selected\n");
+       return;
+     }
+   elm_genlist_item_disabled_set(gli, 1);
+   elm_genlist_item_selected_set(gli, 0);
+   elm_genlist_item_update(gli);
+}
+
+static void
+my_gl_update_all(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   int i = 0;
+   Elm_Genlist_Item *it = elm_genlist_first_item_get(gl);
+   while (it)
+     {
+       elm_genlist_item_update(it);
+       printf("%i\n", i);
+       i++;
+       it = elm_genlist_item_next_get(it);
+     }
+}
+
+static void
+my_gl_first(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   Elm_Genlist_Item *gli = elm_genlist_first_item_get(gl);
+   if (!gli) return;
+   elm_genlist_item_show(gli);
+   elm_genlist_item_selected_set(gli, 1);
+}
+
+static void
+my_gl_last(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *gl = data;
+   Elm_Genlist_Item *gli = elm_genlist_last_item_get(gl);
+   if (!gli) return;
+   elm_genlist_item_show(gli);
+   elm_genlist_item_selected_set(gli, 1);
+}
+
+static Eina_Bool
+my_gl_flush_delay(void *data __UNUSED__)
+{
+   elm_all_flush();
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+my_gl_flush(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   ecore_timer_add(1.2, my_gl_flush_delay, NULL);
+}
+
+void
+test_genlist2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bx, *bx2, *bx3, *bt;
+   Elm_Genlist_Item *gli[10];
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "genlist-2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(gl);
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = gl_label_get;
+   itc1.func.icon_get  = gl_icon_get;
+   itc1.func.state_get = gl_state_get;
+   itc1.func.del       = gl_del;
+
+   gli[0] = elm_genlist_item_append(gl, &itc1,
+                                   (void *)1001/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                   (void *)1001/* func data */);
+   gli[1] = elm_genlist_item_append(gl, &itc1,
+                                   (void *)1002/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                   (void *)1002/* func data */);
+   gli[2] = elm_genlist_item_append(gl, &itc1,
+                                   (void *)1003/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                   (void *)1003/* func data */);
+   gli[3] = elm_genlist_item_prepend(gl, &itc1,
+                                    (void *)1004/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                    (void *)1004/* func data */);
+   gli[4] = elm_genlist_item_prepend(gl, &itc1,
+                                    (void *)1005/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                    (void *)1005/* func data */);
+   gli[5] = elm_genlist_item_insert_before(gl, &itc1,
+                                          (void *)1006/* item data */, NULL/* parent */, gli[2]/* rel */, ELM_GENLIST_ITEM_NONE,
+                                          gl_sel/* func */, (void *)1006/* func data */);
+   gli[6] = elm_genlist_item_insert_after(gl, &itc1,
+                                         (void *)1007/* item data */, NULL/* parent */, gli[2]/* rel */, ELM_GENLIST_ITEM_NONE,
+                                         gl_sel/* func */, (void *)1007/* func data */);
+
+   elm_box_pack_end(bx, gl);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "/\\");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_first, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "\\/");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_last, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "#");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_disable, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "U");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update_all, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "X");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_clear, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "+");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_add, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "-");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_del, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx3 = elm_box_add(win);
+   elm_box_horizontal_set(bx3, 1);
+   elm_box_homogenous_set(bx3, 1);
+   evas_object_size_hint_weight_set(bx3, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx3, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "+ before");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_insert_before, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx3, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "+ after");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_insert_after, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx3, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Flush");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_flush, gl);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx3, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx3);
+   evas_object_show(bx3);
+
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+/*************/
+
+static Elm_Genlist_Item_Class itc2;
+char *gl2_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   const Testitem *tit = data;
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item mode %i", tit->mode);
+   return strdup(buf);
+}
+Evas_Object *gl2_icon_get(void *data, Evas_Object *obj, const char *part)
+{
+   const Testitem *tit = data;
+   char buf[PATH_MAX];
+   Evas_Object *ic = elm_icon_add(obj);
+   if (!strcmp(part, "elm.swallow.icon"))
+     {
+       if (!(tit->mode & 0x3))
+         snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+       else if ((tit->mode & 0x3) == 1)
+         snprintf(buf, sizeof(buf), "%s/images/logo.png", PACKAGE_DATA_DIR);
+       else if ((tit->mode & 0x3) == 2)
+         snprintf(buf, sizeof(buf), "%s/images/panel_01.jpg", PACKAGE_DATA_DIR);
+       else if ((tit->mode & 0x3) == 3)
+         snprintf(buf, sizeof(buf), "%s/images/rock_01.jpg", PACKAGE_DATA_DIR);
+       elm_icon_file_set(ic, buf, NULL);
+     }
+   else if (!strcmp(part, "elm.swallow.end"))
+     {
+       if (!(tit->mode & 0x3))
+         snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", PACKAGE_DATA_DIR);
+       else if ((tit->mode & 0x3) == 1)
+         snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+       else if ((tit->mode & 0x3) == 2)
+         snprintf(buf, sizeof(buf), "%s/images/sky_03.jpg", PACKAGE_DATA_DIR);
+       else if ((tit->mode & 0x3) == 3)
+         snprintf(buf, sizeof(buf), "%s/images/sky_04.jpg", PACKAGE_DATA_DIR);
+       elm_icon_file_set(ic, buf, NULL);
+     }
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   return ic;
+}
+Eina_Bool gl2_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   return EINA_FALSE;
+}
+void gl2_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+static void
+my_gl_update(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Testitem *tit = data;
+   tit->mode++;
+   elm_genlist_item_update(tit->item);
+}
+
+void
+test_genlist3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bx, *bx2, *bt;
+   static Testitem tit[3];
+
+   win = elm_win_add(NULL, "genlist-3", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist 3");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(gl);
+
+   itc2.item_style     = "default";
+   itc2.func.label_get = gl2_label_get;
+   itc2.func.icon_get  = gl2_icon_get;
+   itc2.func.state_get = gl2_state_get;
+   itc2.func.del       = gl2_del;
+
+   tit[0].mode = 0;
+   tit[0].item = elm_genlist_item_append(gl, &itc2,
+                                        &(tit[0])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+   tit[1].mode = 1;
+   tit[1].item = elm_genlist_item_append(gl, &itc2,
+                                        &(tit[1])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+   tit[2].mode = 2;
+   tit[2].item = elm_genlist_item_append(gl, &itc2,
+                                        &(tit[2])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+
+   elm_box_pack_end(bx, gl);
+   evas_object_show(bx);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[1]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[0]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[2]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[1]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[3]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[2]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+/*************/
+
+static void
+my_gl_item_check_changed(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Testitem *tit = data;
+   tit->onoff = elm_check_state_get(obj);
+   printf("item %p onoff = %i\n", tit, tit->onoff);
+}
+
+static Elm_Genlist_Item_Class itc3;
+char *gl3_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   const Testitem *tit = data;
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item mode %i", tit->mode);
+   return strdup(buf);
+}
+Evas_Object *gl3_icon_get(void *data, Evas_Object *obj, const char *part)
+{
+   const Testitem *tit = data;
+   if (!strcmp(part, "elm.swallow.icon"))
+     {
+        Evas_Object *lb;
+        
+        lb = elm_label_add(obj);
+        elm_label_line_wrap_set(lb, 1);
+        elm_label_wrap_width_set(lb, 201);
+        elm_label_label_set(lb, "ashj ascjscjh n asjkl hcjlh ls hzshnn zjh sh zxjcjsnd h dfw sdv edev efe fwefvv vsd cvs ws wf  fvwf wd fwe f  we wef we wfe rfwewef wfv wswf wefg sdfws w wsdcfwcf wsc vdv  sdsd sdcd cv wsc sdcv wsc d sdcdcsd sdcdsc wdvd sdcsd wscxcv wssvd sd");
+        evas_object_show(lb);
+        return lb;
+     }
+   else if (!strcmp(part, "elm.swallow.end"))
+     {
+       Evas_Object *ck;
+       ck = elm_check_add(obj);
+       evas_object_propagate_events_set(ck, 0);
+       elm_check_state_set(ck, tit->onoff);
+       evas_object_smart_callback_add(ck, "changed", my_gl_item_check_changed, data);
+       evas_object_show(ck);
+       return ck;
+     }
+   return NULL;
+}
+Eina_Bool gl3_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   return EINA_FALSE;
+}
+void gl3_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+void
+test_genlist4(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bx, *bx2, *bt;
+   static Testitem tit[3];
+
+   win = elm_win_add(NULL, "genlist-4", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist 4");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   elm_genlist_multi_select_set(gl, 1);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(gl);
+
+   itc3.item_style     = "default";
+   itc3.func.label_get = gl3_label_get;
+   itc3.func.icon_get  = gl3_icon_get;
+   itc3.func.state_get = gl3_state_get;
+   itc3.func.del       = gl3_del;
+
+   tit[0].mode = 0;
+   tit[0].item = elm_genlist_item_append(gl, &itc3,
+                                        &(tit[0])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+   tit[1].mode = 1;
+   tit[1].item = elm_genlist_item_append(gl, &itc3,
+                                        &(tit[1])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+   tit[2].mode = 2;
+   tit[2].item = elm_genlist_item_append(gl, &itc3,
+                                        &(tit[2])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+
+   elm_box_pack_end(bx, gl);
+   evas_object_show(bx);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[1]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[0]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[2]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[1]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[3]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[2]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+
+/*************/
+static void
+my_gl_item_check_changed2(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Testitem *tit = data;
+   tit->onoff = elm_check_state_get(obj);
+   printf("item %p onoff = %i\n", tit, tit->onoff);
+}
+
+static Elm_Genlist_Item_Class itc5;
+char *gl5_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
+{
+   const Testitem *tit = data;
+   char buf[256];
+   if (!strcmp(part, "elm.text"))
+     {
+       snprintf(buf, sizeof(buf), "Item mode %i", tit->mode);
+     }
+   else if (!strcmp(part, "elm.text.sub"))
+     {
+       snprintf(buf, sizeof(buf), "%i bottles on the wall", tit->mode);
+     }
+   return strdup(buf);
+}
+Evas_Object *gl5_icon_get(void *data, Evas_Object *obj, const char *part)
+{
+   const Testitem *tit = data;
+   char buf[PATH_MAX];
+   if (!strcmp(part, "elm.swallow.icon"))
+     {
+       Evas_Object *bx = elm_box_add(obj);
+       Evas_Object *ic;
+       elm_box_horizontal_set(bx, 1);
+       ic = elm_icon_add(obj);
+       snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+       elm_icon_file_set(ic, buf, NULL);
+       elm_icon_scale_set(ic, 0, 0);
+       evas_object_show(ic);
+       elm_box_pack_end(bx, ic);
+       ic = elm_icon_add(obj);
+       elm_icon_file_set(ic, buf, NULL);
+       elm_icon_scale_set(ic, 0, 0);
+       evas_object_show(ic);
+       elm_box_pack_end(bx, ic);
+        elm_box_horizontal_set(bx, 1);
+       evas_object_show(bx);
+       return bx;
+     }
+   else if (!strcmp(part, "elm.swallow.end"))
+     {
+       Evas_Object *ck;
+       ck = elm_check_add(obj);
+       evas_object_propagate_events_set(ck, 0);
+       elm_check_state_set(ck, tit->onoff);
+       evas_object_smart_callback_add(ck, "changed", my_gl_item_check_changed2, data);
+       evas_object_show(ck);
+       return ck;
+     }
+   return NULL;
+}
+Eina_Bool gl5_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   return EINA_FALSE;
+}
+void gl5_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+static void
+item_drag_up(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag up\n");
+}
+
+static void
+item_drag_down(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag down\n");
+}
+
+static void
+item_drag_left(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag left\n");
+}
+
+static void
+item_drag_right(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag right\n");
+}
+
+static void
+scroll_top(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Top edge!\n");
+}
+
+static void
+scroll_bottom(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Bottom edge!\n");
+}
+
+static void
+scroll_left(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Left edge!\n");
+}
+
+static void
+scroll_right(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Right edge!\n");
+}
+
+static void
+item_drag(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag\n");
+}
+
+static void
+item_drag_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag stop\n");
+}
+
+static void
+item_longpress(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("longpress\n");
+}
+
+void
+test_genlist5(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bx, *bx2, *bt;
+   static Testitem tit[3];
+
+   win = elm_win_add(NULL, "genlist-5", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist 5");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   elm_genlist_always_select_mode_set(gl, 1);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(gl);
+   itc5.item_style     = "double_label";
+   itc5.func.label_get = gl5_label_get;
+   itc5.func.icon_get  = gl5_icon_get;
+   itc5.func.state_get = gl5_state_get;
+   itc5.func.del       = gl5_del;
+
+   tit[0].mode = 0;
+   tit[0].item = elm_genlist_item_append(gl, &itc5,
+                                        &(tit[0])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+   tit[1].mode = 1;
+   tit[1].item = elm_genlist_item_append(gl, &itc5,
+                                        &(tit[1])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+   tit[2].mode = 2;
+   tit[2].item = elm_genlist_item_append(gl, &itc5,
+                                        &(tit[2])/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl_sel/* func */,
+                                        NULL/* func data */);
+
+   elm_box_pack_end(bx, gl);
+   evas_object_show(bx);
+
+   evas_object_smart_callback_add(gl, "drag,start,up", item_drag_up, NULL);
+   evas_object_smart_callback_add(gl, "drag,start,down", item_drag_down, NULL);
+   evas_object_smart_callback_add(gl, "drag,start,left", item_drag_left, NULL);
+   evas_object_smart_callback_add(gl, "drag,start,right", item_drag_right, NULL);
+   evas_object_smart_callback_add(gl, "scroll,edge,top", scroll_top, NULL);
+   evas_object_smart_callback_add(gl, "scroll,edge,bottom", scroll_bottom, NULL);
+   evas_object_smart_callback_add(gl, "scroll,edge,left", scroll_left, NULL);
+   evas_object_smart_callback_add(gl, "scroll,edge,right", scroll_right, NULL);
+   evas_object_smart_callback_add(gl, "drag", item_drag, NULL);
+   evas_object_smart_callback_add(gl, "drag,stop", item_drag_stop, NULL);
+   evas_object_smart_callback_add(gl, "longpressed", item_longpress, NULL);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[1]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[0]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[2]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[1]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[3]");
+   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[2]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+/*************/
+
+static Elm_Genlist_Item_Class itc4;
+
+static void
+gl4_sel(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = (Elm_Genlist_Item *)event_info;
+   int depth = 0;
+
+   depth = elm_genlist_item_expanded_depth_get(it);
+   printf("expanded depth for selected item is %d\n", depth);
+
+}
+static void
+gl4_exp(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   Evas_Object *gl = elm_genlist_item_genlist_get(it);
+   int val = (int)(long)elm_genlist_item_data_get(it);
+   val *= 10;
+   elm_genlist_item_append(gl, &itc4,
+                          (void *)(long)(val + 1)/* item data */, it/* parent */,
+                           ELM_GENLIST_ITEM_NONE, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc4,
+                          (void *)(long)(val + 2)/* item data */, it/* parent */,
+                           ELM_GENLIST_ITEM_NONE, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc4,
+                          (void *)(long)(val + 3)/* item data */, it/* parent */,
+                           ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                          NULL/* func data */);
+}
+static void
+gl4_con(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_subitems_clear(it);
+}
+
+static void
+gl4_exp_req(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 1);
+}
+static void
+gl4_con_req(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 0);
+}
+
+char *gl4_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item mode %i", (int)(long)data);
+   return strdup(buf);
+}
+Evas_Object *gl4_icon_get(void *data __UNUSED__, Evas_Object *obj, const char *part)
+{
+   char buf[PATH_MAX];
+   if (!strcmp(part, "elm.swallow.icon"))
+     {
+       Evas_Object *ic = elm_icon_add(obj);
+       snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+       elm_icon_file_set(ic, buf, NULL);
+       evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+       evas_object_show(ic);
+       return ic;
+     }
+   else if (!strcmp(part, "elm.swallow.end"))
+     {
+       Evas_Object *ck;
+       ck = elm_check_add(obj);
+       evas_object_show(ck);
+       return ck;
+     }
+   return NULL;
+}
+Eina_Bool gl4_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   return EINA_FALSE;
+}
+void gl4_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+void
+test_genlist6(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bx, *bx2, *bt;
+
+   win = elm_win_add(NULL, "genlist-tree", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist Tree");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(gl);
+
+   itc4.item_style     = "default";
+   itc4.func.label_get = gl4_label_get;
+   itc4.func.icon_get  = gl4_icon_get;
+   itc4.func.state_get = gl4_state_get;
+   itc4.func.del       = gl4_del;
+
+   elm_genlist_item_append(gl, &itc4,
+                          (void *)1/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc4,
+                          (void *)2/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc4,
+                          (void *)3/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_NONE, gl4_sel/* func */,
+                          NULL/* func data */);
+
+   evas_object_smart_callback_add(gl, "expand,request", gl4_exp_req, gl);
+   evas_object_smart_callback_add(gl, "contract,request", gl4_con_req, gl);
+   evas_object_smart_callback_add(gl, "expanded", gl4_exp, gl);
+   evas_object_smart_callback_add(gl, "contracted", gl4_con, gl);
+
+   elm_box_pack_end(bx, gl);
+   evas_object_show(bx);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[1]");
+//   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[0]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[2]");
+//   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[1]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "[3]");
+//   evas_object_smart_callback_add(bt, "clicked", my_gl_update, &(tit[2]));
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+/*************/
+
+struct genlist7_data
+{
+  Evas_Object *win, *pager;
+};
+
+static Elm_Genlist_Item_Class itc7;
+static void
+gl_sel7(void *data, Evas_Object *obj, void *event_info)
+{
+   if (!event_info) return;
+   elm_genlist_item_item_class_update(event_info, &itc7);
+   printf("sel item data [%p] on genlist obj [%p], item pointer [%p], new item style [%s] \n", data, obj, event_info, itc7.item_style);
+}
+
+static void
+test_genlist7_back_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    struct genlist7_data *info = data;
+    if (!info) return;
+
+    elm_pager_content_pop(info->pager);
+}
+
+static void
+test_genlist7_swipe(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   struct genlist7_data *info = data;
+   Evas_Object *box, *entry, *button;
+   char item_data[] = "Just a simple test";
+
+   if ((!event_info) || (!data)) return;
+
+   box = elm_box_add(info->win);
+   elm_box_homogenous_set(box, 0);
+   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(box);
+
+   entry = elm_scrolled_entry_add(info->win);
+   elm_scrolled_entry_editable_set(entry, EINA_FALSE);
+   elm_scrolled_entry_entry_set(entry, item_data);
+   evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(entry);
+
+   button = elm_button_add(info->win);
+   elm_button_label_set(button, "back");
+   evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(button, EVAS_HINT_FILL, 0);
+   evas_object_smart_callback_add(button, "clicked", test_genlist7_back_cb,
+                                  info);
+   evas_object_show(button);
+
+   elm_box_pack_start(box, entry);
+   elm_box_pack_end(box, button);
+
+   elm_pager_content_push(info->pager, box);
+}
+
+void
+test_genlist7(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *pager;
+   static struct genlist7_data info;
+   static Testitem tit[3];
+
+   win = elm_win_add(NULL, "genlist-7", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist 7");
+   elm_win_autodel_set(win, 1);
+   info.win = win;
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   pager = elm_pager_add(win);
+   elm_win_resize_object_add(win, pager);
+   evas_object_size_hint_weight_set(pager, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(pager, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(pager);
+   info.pager = pager;
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_smart_callback_add(gl, "swipe", test_genlist7_swipe, &info);
+   evas_object_show(gl);
+   elm_pager_content_push(pager, gl);
+
+   itc2.item_style     = "default";
+   itc2.func.label_get = gl2_label_get;
+   itc2.func.icon_get  = gl2_icon_get;
+   itc2.func.state_get = gl2_state_get;
+   itc2.func.del       = gl2_del;
+
+   itc7.item_style     = "double_label";
+   itc7.func.label_get = gl5_label_get;
+   itc7.func.icon_get  = gl5_icon_get;
+   itc7.func.state_get = gl5_state_get;
+   itc7.func.del       = gl5_del;
+
+   tit[0].mode = 0;
+   tit[0].item = elm_genlist_item_append(gl, &itc2,
+                                        &(tit[0])/* item data */, NULL/* parent */,
+                                         ELM_GENLIST_ITEM_NONE, gl_sel7/* func */,
+                                        NULL/* func data */);
+   tit[1].mode = 1;
+   tit[1].item = elm_genlist_item_append(gl, &itc2,
+                                        &(tit[1])/* item data */, NULL/* parent */,
+                                         ELM_GENLIST_ITEM_NONE, gl_sel7/* func */,
+                                        NULL/* func data */);
+   tit[2].mode = 2;
+   tit[2].item = elm_genlist_item_append(gl, &itc2,
+                                        &(tit[2])/* item data */, NULL/* parent */,
+                                         ELM_GENLIST_ITEM_NONE, gl_sel7/* func */,
+                                        NULL/* func data */);
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+/*************/
+
+static Elm_Genlist_Item_Class itc_group;
+char *gl8_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Group Index # %i (Item # %i)",  (int)((long)data / 10), (int)(long)data);
+   return strdup(buf);
+}
+
+static void
+_bt_show_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    elm_genlist_item_top_show(data);
+    //elm_genlist_item_show(data);
+    //elm_genlist_item_middle_show(data);
+}
+static void
+_bt_bring_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    elm_genlist_item_top_bring_in(data);
+    //elm_genlist_item_bring_in(data);
+    //elm_genlist_item_middle_bring_in(data);
+}
+
+void
+test_genlist8(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bt[8], *bx, *bx2, *bx3;
+   Elm_Genlist_Item *gli = NULL, *git = NULL;
+   int i, bt_count, bt_num;
+
+   win = elm_win_add(NULL, "genlist-group", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist Group");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   evas_object_smart_callback_add(gl, "selected", _gl_selected, NULL);
+   evas_object_smart_callback_add(gl, "clicked", _gl_clicked, NULL);
+   evas_object_smart_callback_add(gl, "longpressed", _gl_longpress, NULL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, gl);
+   evas_object_show(gl);
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = gl_label_get;
+   itc1.func.icon_get  = gl_icon_get;
+   itc1.func.state_get = gl_state_get;
+   itc1.func.del       = gl_del;
+
+   itc_group.item_style     = "group_index";
+   itc_group.func.label_get = gl8_label_get;
+   itc_group.func.icon_get  = NULL;
+   itc_group.func.state_get = NULL;
+   itc_group.func.del       = gl_del;
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, EINA_TRUE);
+   elm_box_homogenous_set(bx2, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt_num = 0;
+   bt[bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Show 0");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx2, bt[bt_num]);
+
+   bt[++bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Show 26");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx2, bt[bt_num]);
+
+   bt[++bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Show 101");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx2, bt[bt_num]);
+
+   bt[++bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Show 480");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx2, bt[bt_num]);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx3 = elm_box_add(win);
+   elm_box_horizontal_set(bx3, EINA_TRUE);
+   elm_box_homogenous_set(bx3, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx3, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx3, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt[++bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Bring top 0");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx3, bt[bt_num]);
+
+   bt[++bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Bring top 31");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx3, bt[bt_num]);
+
+   bt[++bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Bring top 239");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx3, bt[bt_num]);
+
+   bt[++bt_num] = elm_button_add(win);
+   elm_button_label_set(bt[bt_num], "Bring top 477");
+   evas_object_size_hint_align_set(bt[bt_num], EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt[bt_num], EVAS_HINT_EXPAND, 0.0);
+   evas_object_show(bt[bt_num]);
+   elm_box_pack_end(bx3, bt[bt_num]);
+
+   elm_box_pack_end(bx, bx3);
+   evas_object_show(bx3);
+
+   bt_count = 0;
+   for (i = 0; i < 500; i++)
+     {
+        if (!(i % 10))
+          {
+             gli = git = elm_genlist_item_append(gl, &itc_group,
+                                           (void *)(long)i/* item data */,
+                                           NULL/* parent */,
+                                           ELM_GENLIST_ITEM_GROUP,
+                                           gl_sel/* func */,
+                                           (void *)(long)(i * 10)/* func data */);
+          }
+        else if (git)
+          {
+             gli = elm_genlist_item_append(gl, &itc1,
+                                           (void *)(long)i/* item data */,
+                                           git/* parent */,
+                                           ELM_GENLIST_ITEM_NONE,
+                                           gl_sel/* func */,
+                                           (void *)(long)(i * 10)/* func data */);
+          }
+        //elm_genlist_item_display_only_set(gli, EINA_TRUE);
+        switch (i)
+          {
+           case 0: 
+              evas_object_smart_callback_add(bt[0], "clicked", _bt_show_cb, gli);
+              evas_object_smart_callback_add(bt[4], "clicked", _bt_bring_cb, gli);
+              break;
+           case 26: 
+              evas_object_smart_callback_add(bt[1], "clicked", _bt_show_cb, gli);
+              break;
+           case 31: 
+              evas_object_smart_callback_add(bt[5], "clicked", _bt_bring_cb, gli);
+              break;
+           case 101: 
+              evas_object_smart_callback_add(bt[2], "clicked", _bt_show_cb, gli);
+              break;
+           case 239: 
+              evas_object_smart_callback_add(bt[6], "clicked", _bt_bring_cb, gli);
+              break;
+           case 477: 
+              evas_object_smart_callback_add(bt[7], "clicked", _bt_bring_cb, gli);
+              break;
+           case 480: 
+              evas_object_smart_callback_add(bt[3], "clicked", _bt_show_cb, gli);
+              break;
+          }
+     }
+
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+}
+
+/*************/
+
+static void
+gl9_exp(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   Evas_Object *gl = elm_genlist_item_genlist_get(it);
+   int val = (int)(long)elm_genlist_item_data_get(it);
+   val *= 10;
+   elm_genlist_item_append(gl, &itc1,
+                           (void *)(long)(val + 1)/* item data */, it/* parent */,
+                           ELM_GENLIST_ITEM_NONE, gl4_sel/* func */,
+                           NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                           (void *)(long)(val + 2)/* item data */, it/* parent */,
+                           ELM_GENLIST_ITEM_NONE, gl4_sel/* func */,
+                           NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                           (void *)(long)(val + 3)/* item data */, it/* parent */,
+                           ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                           NULL/* func data */);
+}
+static void
+gl9_con(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_subitems_clear(it);
+}
+
+static void
+gl9_exp_req(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, EINA_TRUE);
+}
+static void
+gl9_con_req(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, EINA_FALSE);
+}
+
+void
+test_genlist9(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *bx;
+   Elm_Genlist_Item *git;
+
+   win = elm_win_add(NULL, "genlist-group-tree", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist Group Tree");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   gl = elm_genlist_add(win);
+   evas_object_smart_callback_add(gl, "selected", _gl_selected, NULL);
+   evas_object_smart_callback_add(gl, "clicked", _gl_clicked, NULL);
+   evas_object_smart_callback_add(gl, "longpressed", _gl_longpress, NULL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, gl);
+   evas_object_show(gl);
+
+   itc1.item_style     = "default";
+   itc1.func.label_get = gl_label_get;
+   itc1.func.icon_get  = gl_icon_get;
+   itc1.func.state_get = gl_state_get;
+   itc1.func.del       = gl_del;
+
+   itc_group.item_style     = "group_index";
+   itc_group.func.label_get = gl8_label_get;
+   itc_group.func.icon_get  = NULL;
+   itc_group.func.state_get = NULL;
+   itc_group.func.del       = gl_del;
+
+   git = elm_genlist_item_append(gl, &itc_group,
+                          (void *)0/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_GROUP, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                          (void *)1/* item data */, git/* parent */, ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                          (void *)2/* item data */, git/* parent */, ELM_GENLIST_ITEM_NONE, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                          (void *)3/* item data */, git/* parent */, ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                          NULL/* func data */);
+   git = elm_genlist_item_append(gl, &itc_group,
+                          (void *)4/* item data */, NULL/* parent */, ELM_GENLIST_ITEM_GROUP, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                          (void *)5/* item data */, git/* parent */, ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                          (void *)6/* item data */, git/* parent */, ELM_GENLIST_ITEM_NONE, gl4_sel/* func */,
+                          NULL/* func data */);
+   elm_genlist_item_append(gl, &itc1,
+                          (void *)7/* item data */, git/* parent */, ELM_GENLIST_ITEM_SUBITEMS, gl4_sel/* func */,
+                          NULL/* func data */);
+
+   evas_object_smart_callback_add(gl, "expand,request", gl9_exp_req, gl);
+   evas_object_smart_callback_add(gl, "contract,request", gl9_con_req, gl);
+   evas_object_smart_callback_add(gl, "expanded", gl9_exp, gl);
+   evas_object_smart_callback_add(gl, "contracted", gl9_con, gl);
+
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_hover.c b/src/bin/test_hover.c
new file mode 100644 (file)
index 0000000..f4b597c
--- /dev/null
@@ -0,0 +1,172 @@
+#include <Elementary.h>
+#include <elementary_config.h>
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+my_hover_bt(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *hv = data;
+
+   evas_object_show(hv);
+}
+
+void
+test_hover(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt, *hv, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "hover", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Hover");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   hv = elm_hover_add(win);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button");
+   evas_object_smart_callback_add(bt, "clicked", my_hover_bt, hv);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   elm_hover_parent_set(hv, win);
+   elm_hover_target_set(hv, bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Popup");
+   elm_hover_content_set(hv, "middle", bt);
+   evas_object_show(bt);
+
+   bx = elm_box_add(win);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top 1");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top 2");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top 3");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   evas_object_show(bx);
+   elm_hover_content_set(hv, "top", bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Bottom");
+   elm_hover_content_set(hv, "bottom", bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Left");
+   elm_hover_content_set(hv, "left", bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Right");
+   elm_hover_content_set(hv, "right", bt);
+   evas_object_show(bt);
+
+   evas_object_size_hint_min_set(bg, 160, 160);
+   evas_object_size_hint_max_set(bg, 640, 640);
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+void
+test_hover2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt, *hv, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "hover2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Hover 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   hv = elm_hover_add(win);
+   elm_object_style_set(hv, "popout");
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button");
+   evas_object_smart_callback_add(bt, "clicked", my_hover_bt, hv);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   elm_hover_parent_set(hv, win);
+   elm_hover_target_set(hv, bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Popup");
+   elm_hover_content_set(hv, "middle", bt);
+   evas_object_show(bt);
+
+   bx = elm_box_add(win);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top 1");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top 2");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top 3");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(bx);
+   elm_hover_content_set(hv, "top", bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Bot");
+   elm_hover_content_set(hv, "bottom", bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Left");
+   elm_hover_content_set(hv, "left", bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Right");
+   elm_hover_content_set(hv, "right", bt);
+   evas_object_show(bt);
+
+   evas_object_size_hint_min_set(bg, 160, 160);
+   evas_object_size_hint_max_set(bg, 640, 640);
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_hoversel.c b/src/bin/test_hoversel.c
new file mode 100644 (file)
index 0000000..40b68e2
--- /dev/null
@@ -0,0 +1,109 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_hoversel(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "hoversel", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Hoversel");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   bt = elm_hoversel_add(win);
+   elm_hoversel_hover_parent_set(bt, win);
+   elm_hoversel_label_set(bt, "Labels");
+   elm_hoversel_item_add(bt, "Item 1", NULL, ELM_ICON_NONE, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 2", NULL, ELM_ICON_NONE, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 3", NULL, ELM_ICON_NONE, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 4 - Long Label Here", NULL, ELM_ICON_NONE, NULL, NULL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_hoversel_add(win);
+   elm_hoversel_hover_parent_set(bt, win);
+   elm_hoversel_label_set(bt, "Some Icons");
+   elm_hoversel_item_add(bt, "Item 1", NULL, ELM_ICON_NONE, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 2", NULL, ELM_ICON_NONE, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 3", "home", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 4", "close", ELM_ICON_STANDARD, NULL, NULL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_hoversel_add(win);
+   elm_hoversel_hover_parent_set(bt, win);
+   elm_hoversel_label_set(bt, "All Icons");
+   elm_hoversel_item_add(bt, "Item 1", "apps", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 2", "arrow_down", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 3", "home", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 4", "close", ELM_ICON_STANDARD, NULL, NULL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_hoversel_add(win);
+   elm_hoversel_hover_parent_set(bt, win);
+   elm_hoversel_label_set(bt, "All Icons");
+   elm_hoversel_item_add(bt, "Item 1", "apps", ELM_ICON_STANDARD, NULL, NULL);
+   snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+   elm_hoversel_item_add(bt, "Item 2", buf, ELM_ICON_FILE, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 3", "home", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 4", "close", ELM_ICON_STANDARD, NULL, NULL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_hoversel_add(win);
+   elm_hoversel_hover_parent_set(bt, win);
+   elm_hoversel_label_set(bt, "Disabled Hoversel");
+   elm_hoversel_item_add(bt, "Item 1", "apps", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 2", "close", ELM_ICON_STANDARD, NULL, NULL);
+   elm_object_disabled_set(bt, 1);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_hoversel_add(win);
+   elm_hoversel_hover_parent_set(bt, win);
+   elm_hoversel_label_set(bt, "Icon + Label");
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/sky_03.jpg", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_hoversel_icon_set(bt, ic);
+   evas_object_show(ic);
+
+   elm_hoversel_item_add(bt, "Item 1", "apps", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 2", "arrow_down", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 3", "home", ELM_ICON_STANDARD, NULL, NULL);
+   elm_hoversel_item_add(bt, "Item 4", "close", ELM_ICON_STANDARD, NULL, NULL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   evas_object_size_hint_align_set(bt, 0.5, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   evas_object_resize(win, 320, 300);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_icon.c b/src/bin/test_icon.c
new file mode 100644 (file)
index 0000000..966171b
--- /dev/null
@@ -0,0 +1,37 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+icon_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("clicked!\n");
+}
+
+void
+test_icon(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "icon-transparent", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Icon Transparent");
+   elm_win_autodel_set(win, 1);
+   elm_win_alpha_set(win, 1);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_no_scale_set(ic, 1);
+   evas_object_size_hint_weight_set(ic, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(ic, 0.5, 0.5);
+   elm_win_resize_object_add(win, ic);
+   evas_object_show(ic);
+
+   evas_object_smart_callback_add(ic, "clicked", icon_clicked, NULL);
+   
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_icon_desktops.c b/src/bin/test_icon_desktops.c
new file mode 100644 (file)
index 0000000..afc300a
--- /dev/null
@@ -0,0 +1,128 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static Elm_Genlist_Item_Class it_desk;
+
+static char *
+desk_gl_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+#ifdef ELM_EFREET   
+   Efreet_Desktop *d = (Efreet_Desktop *)data;
+   return strdup(d->name);
+#else
+   return NULL;
+   (void)data;
+#endif   
+}
+static Evas_Object *
+desk_gl_icon_get(void *data, Evas_Object *obj, const char *part)
+{
+   // FIXME: elm_icon should grok this
+#ifdef ELM_EFREET   
+   Efreet_Desktop *d = (Efreet_Desktop *)data;
+   const char *path;
+   Evas_Object *ic;
+   ic = elm_icon_add(obj);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   if (!(!strcmp(part, "elm.swallow.icon"))) return ic;
+   if (!d->icon) return ic;
+   path = efreet_icon_path_find(getenv("E_ICON_THEME"), d->icon, 48);
+   if (!path) 
+     {
+        path = efreet_icon_path_find("default", d->icon, 48);
+        if (!path)
+          {
+             path = efreet_icon_path_find("hicolor", d->icon, 48);
+             if (!path)
+               {
+                  path = efreet_icon_path_find("gnome", d->icon, 48);
+                  if (!path)
+                    {
+                       path = efreet_icon_path_find("Human", d->icon, 48);
+                    }
+               }
+          }
+     }
+   if (path)
+     {
+        elm_icon_file_set(ic, path, NULL);
+        return ic;
+     }
+   return ic;
+#else
+   return NULL;
+   (void)data;
+   (void)obj;
+   (void)part;
+#endif   
+}
+static void
+desk_gl_del(void *data, Evas_Object *obj __UNUSED__)
+{
+#ifdef ELM_EFREET   
+   Efreet_Desktop *d = (Efreet_Desktop *)data;
+   efreet_desktop_free(d);
+#else
+   return;
+   (void)data;
+#endif   
+}
+
+#ifdef ELM_EFREET
+static void
+desktop_sel(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("sel\n");
+}
+#endif
+
+void
+test_icon_desktops(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl;
+#ifdef ELM_EFREET
+   Eina_List *desktops;
+#endif
+
+   win = elm_win_add(NULL, "icon_desktops", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Icon Desktops");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   it_desk.item_style     = "default";
+   it_desk.func.label_get = desk_gl_label_get;
+   it_desk.func.icon_get  = desk_gl_icon_get;
+   it_desk.func.state_get = NULL;
+   it_desk.func.del       = desk_gl_del;
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, gl);
+   evas_object_show(gl);
+
+#ifdef ELM_EFREET
+   if (elm_need_efreet())
+     {
+       desktops = efreet_util_desktop_name_glob_list("*");
+       if (desktops)
+         {
+           Efreet_Desktop *d;
+          
+           EINA_LIST_FREE(desktops, d)
+             elm_genlist_item_append(gl, &it_desk, d,
+                                    NULL, ELM_GENLIST_ITEM_NONE,
+                                    desktop_sel, NULL);
+         }
+     }
+#endif
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_index.c b/src/bin/test_index.c
new file mode 100644 (file)
index 0000000..442496c
--- /dev/null
@@ -0,0 +1,255 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static Elm_Genlist_Item_Class itci;
+char *gli_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   char buf[256];
+   int j = (long)data;
+   snprintf(buf, sizeof(buf), "%c%c",
+            'A' + ((j >> 4) & 0xf),
+            'a' + ((j     ) & 0xf)
+            );
+   return strdup(buf);
+}
+
+void
+index_changed2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   // called on a change but delayed in case multiple changes happen in a
+   // short timespan
+   elm_genlist_item_top_bring_in(event_info);
+}
+
+void
+index_changed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   // this is calld on every change, no matter how often
+   // elm_genlist_item_bring_in(event_info);
+}
+
+void
+index_selected(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   // called on final select
+   elm_genlist_item_top_bring_in(event_info);
+}
+
+void
+test_index(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *gl, *id;
+   Elm_Genlist_Item *it;
+   int i, j;
+
+   win = elm_win_add(NULL, "index", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Index");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, gl);
+   evas_object_show(gl);
+   
+   id = elm_index_add(win);
+   evas_object_size_hint_weight_set(id, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, id);
+   
+   evas_object_show(id);
+
+   itci.item_style     = "default";
+   itci.func.label_get = gli_label_get;
+   itci.func.icon_get  = NULL;
+   itci.func.state_get = NULL;
+   itci.func.del       = NULL;
+
+   j = 0;
+   for (i = 0; i < 100; i++)
+     {
+        it = elm_genlist_item_append(gl, &itci,
+                                     (void *)(long)j/* item data */, 
+                                     NULL/* parent */, ELM_GENLIST_ITEM_NONE,
+                                     NULL/* func */, NULL/* func data */);
+        if (!(j & 0xf))
+          {
+             char buf[32];
+             
+             snprintf(buf, sizeof(buf), "%c", 'A' + ((j >> 4) & 0xf));
+             elm_index_item_append(id, buf, it);
+          }
+        j += 2;
+     }
+   evas_object_smart_callback_add(id, "delay,changed", index_changed2, NULL);
+   evas_object_smart_callback_add(id, "changed", index_changed, NULL);
+   evas_object_smart_callback_add(id, "selected", index_selected, NULL);
+   elm_index_item_go(id, 0);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+/***********/
+
+typedef struct _Test_Index2_Elements
+{
+   Evas_Object *entry, *lst, *id;
+} Test_Index2_Elements;
+
+void
+test_index2_del(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   /* FIXME it won't be called if elm_test main window is closed */
+   free(data);
+}
+
+int
+test_index2_cmp(const void *data1, const void *data2)
+{
+   const char *label1, *label2;
+   const Elm_List_Item *it1 = data1;
+   const Elm_List_Item *it2 = data2;
+
+   label1 = elm_list_item_label_get(it1);
+   label2 = elm_list_item_label_get(it2);
+
+   return strcasecmp(label1, label2);
+}
+
+int
+test_index2_icmp(const void *data1, const void *data2)
+{
+   const char *label1, *label2;
+   const Elm_Index_Item *it1 = data1;
+   const Elm_Index_Item *it2 = data2;
+
+   label1 = elm_index_item_letter_get(it1);
+   label2 = elm_index_item_letter_get(it2);
+
+   return strcasecmp(label1, label2);
+}
+
+void
+test_index2_it_add(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Test_Index2_Elements *gui = data;
+   Elm_List_Item *it;
+   const char *label;
+   char letter[2];
+
+   label = elm_scrolled_entry_entry_get(gui->entry);
+   snprintf(letter, sizeof(letter), "%c", label[0]);
+   it = elm_list_item_sorted_insert(gui->lst, label, NULL, NULL, NULL, NULL,
+        test_index2_cmp);
+   elm_index_item_sorted_insert(gui->id, letter, it, test_index2_icmp,
+        test_index2_cmp);
+   elm_list_go(gui->lst);
+   /* FIXME it's not showing the recently added item */
+   elm_list_item_show(it);
+}
+
+void
+test_index2_it_del(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Test_Index2_Elements *gui = data;
+   const char *label, *label_next;
+   Elm_List_Item *it, *it_next;
+
+   it = elm_list_selected_item_get(obj);
+   it_next = elm_list_item_next(it);
+
+   if (!it_next)
+     {
+       elm_index_item_del(gui->id, it);
+       elm_list_item_del(it);
+       return;
+     }
+
+   label = elm_list_item_label_get(it);
+   label_next = elm_list_item_label_get(it_next);
+
+   if (label[0] == label_next[0])
+     {
+       Elm_Index_Item *iit;
+       iit = elm_index_item_find(gui->id, it);
+       elm_index_item_data_set(iit, it_next);
+     }
+   else
+     elm_index_item_del(gui->id, it);
+
+   elm_list_item_del(it);
+}
+
+void
+test_index2_id_changed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   elm_list_item_show(event_info);
+}
+
+void
+test_index2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *box, *bt;
+   Test_Index2_Elements *gui;
+
+   gui = malloc(sizeof(*gui));
+
+   win = elm_win_add(NULL, "sorted-index-list", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Sorted Index and List");
+   evas_object_smart_callback_add(win, "delete-request", test_index2_del, gui);
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   box = elm_box_add(win);
+   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, box);
+   evas_object_show(box);
+
+   gui->id = elm_index_add(win);
+   evas_object_size_hint_weight_set(gui->id, EVAS_HINT_EXPAND,
+        EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, gui->id);
+   evas_object_smart_callback_add(gui->id, "delay,changed",
+        test_index2_id_changed, NULL);
+   evas_object_show(gui->id);
+
+   gui->entry = elm_scrolled_entry_add(win);
+   elm_scrolled_entry_entry_set(gui->entry, "Label");
+   elm_scrolled_entry_single_line_set(gui->entry, EINA_TRUE);
+   evas_object_size_hint_weight_set(gui->entry, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_fill_set(gui->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(box, gui->entry);
+   evas_object_show(gui->entry);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Add");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(box, bt);
+   evas_object_smart_callback_add(bt, "clicked", test_index2_it_add, gui);
+   evas_object_show(bt);
+
+   gui->lst = elm_list_add(win);
+   elm_box_pack_end(box, gui->lst);
+   evas_object_size_hint_weight_set(gui->lst, EVAS_HINT_EXPAND,
+        EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(gui->lst, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(gui->lst, "selected", test_index2_it_del,
+        gui);
+   elm_list_go(gui->lst);
+   evas_object_show(gui->lst);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_inwin.c b/src/bin/test_inwin.c
new file mode 100644 (file)
index 0000000..8a95071
--- /dev/null
@@ -0,0 +1,71 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_inwin(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *inwin, *lb;
+
+   win = elm_win_add(NULL, "inwin", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Inwin");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   inwin = elm_win_inwin_add(win);
+   evas_object_show(inwin);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "This is an \"inwin\" - a window in a<br>"
+                      "window. This is handy for quick popups<br>"
+                      "you want centered, taking over the window<br>"
+                      "until dismissed somehow. Unlike hovers they<br>"
+                      "don't hover over their target.");
+   elm_win_inwin_content_set(inwin, lb);
+   evas_object_show(lb);
+
+   evas_object_resize(win, 320, 240);
+   evas_object_show(win);
+}
+
+void
+test_inwin2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *inwin, *lb;
+
+   win = elm_win_add(NULL, "inwin", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Inwin");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   inwin = elm_win_inwin_add(win);
+   elm_object_style_set(inwin, "minimal_vertical");
+   evas_object_show(inwin);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "This is an \"inwin\" - a window in a<br>"
+                      "window. This is handy for quick popups<br>"
+                      "you want centered, taking over the window<br>"
+                      "until dismissed somehow. Unlike hovers they<br>"
+                      "don't hover over their target.<br>"
+                      "<br>"
+                      "This inwin style compacts itself vertically<br>"
+                      "to the size of its contents minimum size.");
+   elm_win_inwin_content_set(inwin, lb);
+   evas_object_show(lb);
+
+   evas_object_resize(win, 320, 240);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_label.c b/src/bin/test_label.c
new file mode 100644 (file)
index 0000000..d26841e
--- /dev/null
@@ -0,0 +1,78 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+void
+test_label(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *lb;
+
+   win = elm_win_add(NULL, "label", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Label");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, 
+                       "<b>This is a small label</b>"
+                       );
+   evas_object_size_hint_weight_set(lb, 0.0, 0.0);
+   evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, 
+                       "This is a larger label with newlines<br>"
+                       "to make it bigger, bit it won't expand or wrap<br>"
+                       "just be a block of text that can't change its<br>"
+                       "formatting as it's fixed based on text<br>"
+                       );
+   evas_object_size_hint_weight_set(lb, 0.0, 0.0);
+   evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   lb = elm_label_add(win);
+   elm_label_line_wrap_set(lb, 1);
+   elm_label_label_set(lb,
+                       "<b>"
+                       "This is more text designed to line-wrap here as "
+                       "This object is resized horizontally. As it is "
+                       "resized vertically though, nothing should change. "
+                       "The amount of space allocated vertically should "
+                       "change as horizontal size changes."
+                       "</b>"
+                       );
+   evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, 
+                       "This small label set to wrap"
+                       );
+   evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+   
+   evas_object_resize(win, 320, 300);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_launcher.c b/src/bin/test_launcher.c
new file mode 100644 (file)
index 0000000..f99626a
--- /dev/null
@@ -0,0 +1,922 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+mode_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *mb;
+   Eina_List *mbs, *l;
+   
+   mbs = evas_object_data_get(win, "mbs");
+   EINA_LIST_FOREACH(mbs, l, mb)
+     {
+        if (elm_mapbuf_enabled_get(mb))
+          elm_mapbuf_enabled_set(mb, 0);
+        else
+          elm_mapbuf_enabled_set(mb, 1);
+     }
+}
+
+static void
+full_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   elm_win_fullscreen_set(win, !elm_win_fullscreen_get(win));
+}
+
+static void
+alpha_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *mb;
+   Eina_List *mbs, *l;
+   
+   mbs = evas_object_data_get(win, "mbs");
+   EINA_LIST_FOREACH(mbs, l, mb)
+     {
+        elm_mapbuf_alpha_set(mb, elm_check_state_get(obj));
+     }
+}
+
+static void
+smooth_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *mb;
+   Eina_List *mbs, *l;
+   
+   mbs = evas_object_data_get(win, "mbs");
+   EINA_LIST_FOREACH(mbs, l, mb)
+     {
+        elm_mapbuf_smooth_set(mb, elm_check_state_get(obj));
+     }
+}
+
+static void
+close_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_del(data);
+}
+
+static Eina_Bool
+tim_cb(void *data)
+{
+   Evas_Object *tb, *sc, *mb;
+   Eina_List *list, *l;
+   
+   evas_object_data_del(data, "timer");
+   tb = evas_object_data_get(data, "tb");
+   sc = evas_object_data_get(data, "sc");
+   elm_object_scroll_freeze_push(sc);
+   evas_object_data_set(data, "dragging", (void *)(long)(1));
+   evas_object_color_set(data, 255, 255, 255, 255);
+   list = (Eina_List *)evas_object_data_get
+      (elm_object_top_widget_get(data), "mbs");
+   EINA_LIST_FOREACH(list, l, mb)
+      evas_object_color_set(mb, 128, 128, 128, 128);
+   elm_table_unpack(tb, data);
+   return EINA_FALSE;
+}
+
+static void
+ic_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Ecore_Timer *tim;
+   
+   tim = evas_object_data_get(obj, "timer");
+   if (tim)
+     {
+        evas_object_data_del(obj, "timer");
+        ecore_timer_del(tim);
+     }
+}
+
+static void
+ic_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev = event_info;
+   Ecore_Timer *tim;
+   Evas_Coord x, y, w, h;
+   
+   evas_object_color_set(data, 128, 0, 0, 128);
+   
+   tim = evas_object_data_get(obj, "timer");
+   if (tim) evas_object_data_del(obj, "timer");
+   tim = ecore_timer_add(1.0, tim_cb, obj);
+   evas_object_data_set(obj, "timer", tim);
+
+   evas_object_geometry_get(data, &x, &y, &w, &h);
+   evas_object_data_set(obj, "x", (void *)(long)(ev->canvas.x));
+   evas_object_data_set(obj, "y", (void *)(long)(ev->canvas.y));
+   evas_object_data_set(obj, "px", (void *)(long)(x));
+   evas_object_data_set(obj, "py", (void *)(long)(y));
+   
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     {
+        printf("double click %p\n", obj);
+     }
+}
+
+static void
+ic_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Up *ev = event_info;
+   Ecore_Timer *tim;
+   
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+   evas_object_color_set(data, 255, 255, 255, 255);
+   tim = evas_object_data_get(obj, "timer");
+   if (tim)
+     {
+        evas_object_data_del(obj, "timer");
+        ecore_timer_del(tim);
+     }
+   if (evas_object_data_get(obj, "dragging"))
+     {
+        Evas_Object *tb, *sc, *mb;
+        Eina_List *list, *l;
+        int tbx, tby;
+        
+        evas_object_data_del(obj, "dragging");
+        tb = evas_object_data_get(obj, "tb");
+        sc = evas_object_data_get(obj, "sc");
+        elm_object_scroll_freeze_pop(sc);
+        tbx = (int)(long)evas_object_data_get(obj, "tbx");
+        tby = (int)(long)evas_object_data_get(obj, "tby");
+        elm_table_pack(tb, obj, tbx, tby, 1, 1);
+        list = (Eina_List *)evas_object_data_get
+           (elm_object_top_widget_get(obj), "mbs");
+        EINA_LIST_FOREACH(list, l, mb)
+           evas_object_color_set(mb, 255, 255, 255, 255);
+     }
+}
+
+static void
+ic_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Move *ev = event_info;
+   if (evas_object_data_get(obj, "dragging"))
+     {
+        Evas_Coord x, y, px, py;
+        
+        x = (Evas_Coord)(long)evas_object_data_get(obj, "x");
+        y = (Evas_Coord)(long)evas_object_data_get(obj, "y");
+        px = (Evas_Coord)(long)evas_object_data_get(obj, "px");
+        py = (Evas_Coord)(long)evas_object_data_get(obj, "py");
+        evas_object_move(obj, 
+                         px + ev->cur.canvas.x - x, 
+                         py + ev->cur.canvas.y - y);
+    }
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     {
+        Ecore_Timer *tim;
+        
+        tim = evas_object_data_get(obj, "timer");
+        if (tim)
+          {
+             evas_object_data_del(obj, "timer");
+             ecore_timer_del(tim);
+          }
+        evas_object_color_set(data, 255, 255, 255, 255);
+        return;
+     }
+}
+
+void
+test_launcher(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *sc, *tb, *pad, *bt, *ic, *lb, *tb2, *mb, *ck, *bx, *bx2;
+   int i, j, k, n, m;
+   char buf[PATH_MAX];
+   const char *names[] =
+     {
+        "Hello",    "World",    "Spam",  "Egg", 
+        "Ham",      "Good",     "Bad",   "Milk", 
+        "Smell",    "Of",       "Sky",   "Gold",
+        "Hole",     "Pig",      "And",   "Calm"
+     };
+   Eina_List *mbs = NULL;
+   
+   win = elm_win_add(NULL, "launcher", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Launcher");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/sky_04.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_box_homogenous_set(bx, 1);
+   elm_box_horizontal_set(bx, 1);
+   
+   sc = elm_scroller_add(win);
+   elm_scroller_bounce_set(sc, 1, 0);
+   elm_scroller_policy_set(sc, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   
+   n = 0; m = 0;
+   for (k = 0 ; k < 8; k++)
+     {
+        tb = elm_table_add(win);
+        evas_object_size_hint_weight_set(tb, 0.0, 0.0);
+        evas_object_size_hint_align_set(tb, 0.5, 0.5);
+
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 470, 4);
+        evas_object_size_hint_weight_set(pad, 0.0, 0.0);
+        evas_object_size_hint_align_set(pad, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        elm_table_pack(tb, pad, 1, 0, 5, 1);
+        
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 470, 4);
+        evas_object_size_hint_weight_set(pad, 0.0, 0.0);
+        evas_object_size_hint_align_set(pad, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        elm_table_pack(tb, pad, 1, 11, 5, 1);
+        
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 4, 4);
+        evas_object_size_hint_weight_set(pad, 0.0, 0.0);
+        evas_object_size_hint_align_set(pad, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        elm_table_pack(tb, pad, 0, 1, 1, 10);
+        
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 4, 4);
+        evas_object_size_hint_weight_set(pad, 0.0, 0.0);
+        evas_object_size_hint_align_set(pad, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        elm_table_pack(tb, pad, 6, 1, 1, 10);
+
+        mb = elm_mapbuf_add(win);
+        elm_mapbuf_content_set(mb, tb);
+        evas_object_show(tb);
+        
+        for (j = 0; j < 5; j++)
+          {
+             for (i = 0; i < 5; i++)
+               {
+                  ic = elm_icon_add(win);
+                  elm_object_scale_set(ic, 0.5);
+                  snprintf(buf, sizeof(buf), "%s/images/icon_%02i.png", PACKAGE_DATA_DIR, n);
+                  elm_icon_file_set(ic, buf, NULL);
+                  elm_icon_scale_set(ic, 0, 0);
+                  evas_object_size_hint_weight_set(ic, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                  evas_object_size_hint_align_set(ic, 0.5, 0.5);
+                  elm_table_pack(tb, ic, 1 + i, 1 + (j * 2), 1, 1);
+                  evas_object_show(ic);
+                  
+                  lb = elm_label_add(win);
+                  elm_object_style_set(lb, "marker");
+                  elm_label_label_set(lb, names[m]);
+                  evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                  evas_object_size_hint_align_set(lb, 0.5, 0.5);
+                  elm_table_pack(tb, lb, 1 + i, 1 + (j * 2) + 1, 1, 1);
+                  evas_object_show(lb);
+                  
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_DEL, ic_del_cb, ic);
+                  
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_DOWN, ic_down_cb, ic);
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_UP,   ic_up_cb,   ic);
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_MOVE, ic_move_cb, ic);
+                  
+                  evas_object_data_set(ic, "lb", lb);
+                  evas_object_data_set(ic, "tb", tb);
+                  evas_object_data_set(ic, "sc", sc);
+                  evas_object_data_set(ic, "bx", bx);
+                  evas_object_data_set(ic, "mb", mb);
+                  evas_object_data_set(ic, "tbx", (void *)(long)(1 + i));
+                  evas_object_data_set(ic, "tby", (void *)(long)(1 + (j * 2)));
+                  
+                  n++; if (n > 23) n = 0;
+                  m++; if (m > 15) m = 0;
+               }
+          }
+        
+        elm_box_pack_end(bx, mb);
+        evas_object_show(mb);
+        
+        mbs = eina_list_append(mbs, mb);
+     }
+
+   // fixme: free mbs
+   evas_object_data_set(win, "mbs", mbs);
+   
+   bx2 = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_horizontal_set(bx2, 0);
+   elm_win_resize_object_add(win, bx2);
+   evas_object_show(bx2);
+   
+   elm_scroller_content_set(sc, bx);
+   evas_object_show(bx);
+   
+   elm_scroller_page_relative_set(sc, 1.0, 1.0);
+   evas_object_show(sc);
+
+   tb2 = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_fill_set(tb2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx2, tb2);
+
+   elm_box_pack_end(bx2, sc);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Map");
+   elm_check_state_set(ck, 0);
+   evas_object_smart_callback_add(ck, "changed", mode_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.05, 0.99);
+   elm_table_pack(tb2, ck, 0, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "A");
+   elm_check_state_set(ck, 1);
+   evas_object_smart_callback_add(ck, "changed", alpha_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.20, 0.99);
+   elm_table_pack(tb2, ck, 1, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Smo");
+   elm_check_state_set(ck, 1);
+   evas_object_smart_callback_add(ck, "changed", smooth_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.40, 0.99);
+   elm_table_pack(tb2, ck, 2, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "FS");
+   elm_check_state_set(ck, 0);
+   evas_object_smart_callback_add(ck, "changed", full_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.5, 0.99);
+   elm_table_pack(tb2, ck, 3, 0, 1, 1);
+   evas_object_show(ck);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", close_cb, win);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.95, 0.99);
+   elm_table_pack(tb2, bt, 4, 0, 1, 1);
+   evas_object_show(bt);
+   
+   evas_object_show(tb2);
+
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+}
+
+void
+test_launcher2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *sc, *bt, *tb2, *mb, *ck, *bx, *ly;
+   int k;
+   char buf[PATH_MAX];
+   Eina_List *mbs = NULL;
+   
+   win = elm_win_add(NULL, "launcher", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Launcher");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/sky_03.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+   
+   bx = elm_box_add(win);
+   elm_box_homogenous_set(bx, 1);
+   elm_box_horizontal_set(bx, 1);
+   
+   for (k = 0 ; k < 8; k++)
+     {
+        ly = elm_layout_add(win);
+        snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+        elm_layout_file_set(ly, buf, "layout");
+        evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Button 1");
+        elm_layout_content_set(ly, "element1", bt);
+        evas_object_show(bt);
+        
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Button 2");
+        elm_layout_content_set(ly, "element2", bt);
+        evas_object_show(bt);
+        
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Button 3");
+        elm_layout_content_set(ly, "element3", bt);
+        evas_object_show(bt);
+        
+        mb = elm_mapbuf_add(win);
+        elm_mapbuf_content_set(mb, ly);
+        evas_object_show(ly);
+        
+        elm_box_pack_end(bx, mb);
+        evas_object_show(mb);
+        
+        mbs = eina_list_append(mbs, mb);
+     }
+
+   // fixme: free mbs
+   evas_object_data_set(win, "mbs", mbs);
+   
+   sc = elm_scroller_add(win);
+   elm_scroller_bounce_set(sc, 1, 0);
+   elm_scroller_policy_set(sc, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, sc);
+   
+   elm_scroller_content_set(sc, bx);
+   evas_object_show(bx);
+   
+   elm_scroller_page_relative_set(sc, 1.0, 1.0);
+   evas_object_show(sc);
+
+   tb2 = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, tb2);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Map");
+   elm_check_state_set(ck, 0);
+   evas_object_smart_callback_add(ck, "changed", mode_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.05, 0.99);
+   elm_table_pack(tb2, ck, 0, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "A");
+   elm_check_state_set(ck, 1);
+   evas_object_smart_callback_add(ck, "changed", alpha_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.20, 0.99);
+   elm_table_pack(tb2, ck, 1, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Smo");
+   elm_check_state_set(ck, 1);
+   evas_object_smart_callback_add(ck, "changed", smooth_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.40, 0.99);
+   elm_table_pack(tb2, ck, 2, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "FS");
+   elm_check_state_set(ck, 0);
+   evas_object_smart_callback_add(ck, "changed", full_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.5, 0.99);
+   elm_table_pack(tb2, ck, 3, 0, 1, 1);
+   evas_object_show(ck);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", close_cb, win);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.95, 0.99);
+   elm_table_pack(tb2, bt, 4, 0, 1, 1);
+   evas_object_show(bt);
+   
+   evas_object_show(tb2);
+
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+}
+
+static void
+l3_mode_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *mb;
+   Eina_List *mbs, *l;
+   
+   mbs = evas_object_data_get(win, "mbs");
+   EINA_LIST_FOREACH(mbs, l, mb)
+     {
+        if (elm_mapbuf_enabled_get(mb))
+          elm_mapbuf_enabled_set(mb, 0);
+        else
+          elm_mapbuf_enabled_set(mb, 1);
+     }
+}
+
+static void
+l3_full_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   elm_win_fullscreen_set(win, !elm_win_fullscreen_get(win));
+}
+
+static void
+l3_alpha_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *mb;
+   Eina_List *mbs, *l;
+   
+   mbs = evas_object_data_get(win, "mbs");
+   EINA_LIST_FOREACH(mbs, l, mb)
+     {
+        elm_mapbuf_alpha_set(mb, elm_check_state_get(obj));
+     }
+}
+
+static void
+l3_smooth_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *mb;
+   Eina_List *mbs, *l;
+   
+   mbs = evas_object_data_get(win, "mbs");
+   EINA_LIST_FOREACH(mbs, l, mb)
+     {
+        elm_mapbuf_smooth_set(mb, elm_check_state_get(obj));
+     }
+}
+
+static void
+l3_hidden_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *mb;
+   Eina_List *mbs, *l;
+   
+   mbs = evas_object_data_get(win, "mbs");
+   EINA_LIST_FOREACH(mbs, l, mb)
+     {
+        if (evas_object_visible_get(mb)) evas_object_hide(mb);
+        else evas_object_show(mb);
+     }
+}
+
+static void
+l3_close_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_del(data);
+}
+
+static Eina_Bool
+l3_tim_cb(void *data)
+{
+   Evas_Object *ly, *ly2, *sc, *mb;
+   Eina_List *list, *l;
+   char buf[256];
+   int slx, sly;
+   
+   evas_object_data_del(data, "timer");
+   ly = evas_object_data_get(data, "ly");
+   ly2 = evas_object_data_get(data, "ly2");
+   sc = evas_object_data_get(data, "sc");
+   elm_object_scroll_freeze_push(sc);
+   evas_object_data_set(data, "dragging", (void *)(long)1);
+   evas_object_color_set(data, 255, 255, 255, 255);
+   list = (Eina_List *)evas_object_data_get
+      (elm_object_top_widget_get(data), "mbs");
+   EINA_LIST_FOREACH(list, l, mb)
+      evas_object_color_set(mb, 128, 128, 128, 128);
+   slx = (int)(long)evas_object_data_get(data, "slx");
+   sly = (int)(long)evas_object_data_get(data, "sly");
+   snprintf(buf, sizeof(buf), "slot.%i.%i", slx, sly);
+   elm_layout_content_unset(ly, buf);
+   edje_object_signal_emit(elm_layout_edje_get(ly2), "drag", "app");
+   return EINA_FALSE;
+}
+
+static void
+l3_ic_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Ecore_Timer *tim;
+   
+   tim = evas_object_data_get(obj, "timer");
+   if (tim)
+     {
+        evas_object_data_del(obj, "timer");
+        ecore_timer_del(tim);
+     }
+}
+
+static void
+l3_ic_down_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev = event_info;
+   Ecore_Timer *tim;
+   Evas_Coord x, y, w, h;
+   Evas_Object *ly2;
+   
+   tim = evas_object_data_get(obj, "timer");
+   if (tim) evas_object_data_del(obj, "timer");
+   tim = ecore_timer_add(1.0, l3_tim_cb, obj);
+   evas_object_data_set(obj, "timer", tim);
+
+   ly2 = evas_object_data_get(obj, "ly2");
+   evas_object_geometry_get(ly2, &x, &y, &w, &h);
+   evas_object_data_set(obj, "x", (void *)(long)(ev->canvas.x));
+   evas_object_data_set(obj, "y", (void *)(long)(ev->canvas.y));
+   evas_object_data_set(obj, "px", (void *)(long)(x));
+   evas_object_data_set(obj, "py", (void *)(long)(y));
+   
+   edje_object_signal_emit(elm_layout_edje_get(ly2), "click", "app");
+   
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     {
+        printf("double click %p\n", obj);
+     }
+}
+
+static void
+l3_ic_up_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Up *ev = event_info;
+   Ecore_Timer *tim;
+   Evas_Object *ly2;
+   
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+   
+   ly2 = evas_object_data_get(obj, "ly2");
+   tim = evas_object_data_get(obj, "timer");
+   if (tim)
+     {
+        evas_object_data_del(obj, "timer");
+        ecore_timer_del(tim);
+     }
+   if (evas_object_data_get(obj, "dragging"))
+     {
+        Evas_Object *ly, *sc, *mb;
+        Eina_List *list, *l;
+        int slx, sly;
+        char buf[256];
+        
+        evas_object_data_del(obj, "dragging");
+        ly = evas_object_data_get(obj, "ly");
+        sc = evas_object_data_get(obj, "sc");
+        elm_object_scroll_freeze_pop(sc);
+        slx = (int)(long)evas_object_data_get(obj, "slx");
+        sly = (int)(long)evas_object_data_get(obj, "sly");
+        snprintf(buf, sizeof(buf), "slot.%i.%i", slx, sly);
+        elm_layout_content_set(ly, buf, ly2);
+        list = (Eina_List *)evas_object_data_get
+           (elm_object_top_widget_get(obj), "mbs");
+        EINA_LIST_FOREACH(list, l, mb)
+           evas_object_color_set(mb, 255, 255, 255, 255);
+        edje_object_signal_emit(elm_layout_edje_get(ly2), "drop", "app");
+     }
+   else
+      edje_object_signal_emit(elm_layout_edje_get(ly2), "unclick", "app");
+}
+
+static void
+l3_ic_move_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Object *ly2;
+   
+   ly2 = evas_object_data_get(obj, "ly2");
+   
+   if (evas_object_data_get(obj, "dragging"))
+     {
+        Evas_Coord x, y, px, py;
+        
+        x = (Evas_Coord)(long)evas_object_data_get(obj, "x");
+        y = (Evas_Coord)(long)evas_object_data_get(obj, "y");
+        px = (Evas_Coord)(long)evas_object_data_get(obj, "px");
+        py = (Evas_Coord)(long)evas_object_data_get(obj, "py");
+        evas_object_move(ly2, 
+                         px + ev->cur.canvas.x - x, 
+                         py + ev->cur.canvas.y - y);
+    }
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     {
+        Ecore_Timer *tim;
+        
+        tim = evas_object_data_get(obj, "timer");
+        if (tim)
+          {
+             evas_object_data_del(obj, "timer");
+             ecore_timer_del(tim);
+          }
+        edje_object_signal_emit(elm_layout_edje_get(ly2), "cancel", "app");
+        return;
+     }
+}
+
+void
+test_launcher3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *sc, *tb, *pad, *bt, *ic, *tb2, *mb, *ck, *bx, *bx2, *ly, *ly2;
+   int i, j, k, n, m;
+   char buf[PATH_MAX];
+   const char *names[] =
+     {
+        "Hello",    "World",    "Spam",  "Egg", 
+        "Ham",      "Good",     "Bad",   "Milk", 
+        "Smell",    "Of",       "Sky",   "Gold",
+        "Hole",     "Pig",      "And",   "Calm"
+     };
+   Eina_List *mbs = NULL;
+   
+   win = elm_win_add(NULL, "launcher", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Launcher");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/sky_04.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_homogenous_set(bx, 1);
+   elm_box_horizontal_set(bx, 1);
+   
+   sc = elm_scroller_add(win);
+   elm_scroller_bounce_set(sc, 1, 0);
+   elm_scroller_policy_set(sc, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   
+   n = 0; m = 0;
+   for (k = 0 ; k < 8; k++)
+     {
+        tb = elm_table_add(win);
+        evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 450, 10);
+        elm_table_pack(tb, pad, 1, 0, 1, 1);
+        
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 450, 10);
+        elm_table_pack(tb, pad, 1, 2, 1, 1);
+        
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 10, 450);
+        elm_table_pack(tb, pad, 0, 1, 1, 1);
+        
+        pad = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_size_hint_min_set(pad, 10, 450);
+        elm_table_pack(tb, pad, 2, 1, 1, 1);
+
+        mb = elm_mapbuf_add(win);
+        mbs = eina_list_append(mbs, mb);
+        
+        elm_mapbuf_content_set(mb, tb);
+        evas_object_show(tb);
+        elm_box_pack_end(bx, mb);
+        evas_object_show(mb);
+        
+        ly = elm_layout_add(win);
+        snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+        elm_layout_file_set(ly, buf, "launcher_page");
+        evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(ly, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        elm_table_pack(tb, ly, 1, 1, 1, 1);
+        evas_object_show(ly);
+        
+        for (j = 0; j < 4; j++)
+          {
+             for (i = 0; i < 4; i++)
+               {
+                  ly2 = elm_layout_add(win);
+                  snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+                  elm_layout_file_set(ly2, buf, "launcher_icon");
+                  evas_object_size_hint_weight_set(ly2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                  evas_object_size_hint_align_set(ly2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+                  edje_object_part_text_set(elm_layout_edje_get(ly2), "label", names[m]);
+
+                  ic = elm_icon_add(win);
+                  elm_object_scale_set(ic, 0.5);
+                  snprintf(buf, sizeof(buf), "%s/images/icon_%02i.png", PACKAGE_DATA_DIR, n);
+                  elm_icon_file_set(ic, buf, NULL);
+                  elm_icon_scale_set(ic, 0, 0);
+                  evas_object_size_hint_weight_set(ic, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+                  evas_object_size_hint_align_set(ic, 0.5, 0.5);
+                  elm_layout_content_set(ly2, "slot", ic);
+                  evas_object_show(ic);
+                  
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_DEL, l3_ic_del_cb, ic);
+                  
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_DOWN, l3_ic_down_cb, ic);
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_UP,   l3_ic_up_cb,   ic);
+                  evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_MOVE, l3_ic_move_cb, ic);
+                  
+                  evas_object_data_set(ic, "ly", ly);
+                  evas_object_data_set(ic, "ly2", ly2);
+                  evas_object_data_set(ic, "sc", sc);
+                  evas_object_data_set(ic, "bx", bx);
+                  evas_object_data_set(ic, "mb", mb);
+                  evas_object_data_set(ic, "slx", (void *)(long)(i));
+                  evas_object_data_set(ic, "sly", (void *)(long)(j));
+                  
+                  snprintf(buf, sizeof(buf), "slot.%i.%i", i, j);
+                  elm_layout_content_set(ly, buf, ly2);
+                  evas_object_show(ly2);
+                  
+                  n++; if (n > 23) n = 0;
+                  m++; if (m > 15) m = 0;
+               }
+          }
+     }
+
+   // fixme: free mbs
+   evas_object_data_set(win, "mbs", mbs);
+   
+   bx2 = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_horizontal_set(bx2, 0);
+   elm_win_resize_object_add(win, bx2);
+   evas_object_show(bx2);
+   
+   elm_scroller_content_set(sc, bx);
+   evas_object_show(bx);
+   
+   elm_scroller_page_relative_set(sc, 1.0, 1.0);
+   evas_object_show(sc);
+
+   tb2 = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_fill_set(tb2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx2, tb2);
+
+   elm_box_pack_end(bx2, sc);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Map");
+   elm_check_state_set(ck, 0);
+   evas_object_smart_callback_add(ck, "changed", l3_mode_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.05, 0.99);
+   elm_table_pack(tb2, ck, 0, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "A");
+   elm_check_state_set(ck, 1);
+   evas_object_smart_callback_add(ck, "changed", l3_alpha_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.20, 0.99);
+   elm_table_pack(tb2, ck, 1, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Smo");
+   elm_check_state_set(ck, 1);
+   evas_object_smart_callback_add(ck, "changed", l3_smooth_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.40, 0.99);
+   elm_table_pack(tb2, ck, 2, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "FS");
+   elm_check_state_set(ck, 0);
+   evas_object_smart_callback_add(ck, "changed", l3_full_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.5, 0.99);
+   elm_table_pack(tb2, ck, 3, 0, 1, 1);
+   evas_object_show(ck);
+   
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "Hid");
+   elm_check_state_set(ck, 0);
+   evas_object_smart_callback_add(ck, "changed", l3_hidden_cb, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.5, 0.99);
+   elm_table_pack(tb2, ck, 4, 0, 1, 1);
+   evas_object_show(ck);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", l3_close_cb, win);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.95, 0.99);
+   elm_table_pack(tb2, bt, 5, 0, 1, 1);
+   evas_object_show(bt);
+   
+   evas_object_show(tb2);
+
+   evas_object_resize(win, 480, 800);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_layout.c b/src/bin/test_layout.c
new file mode 100644 (file)
index 0000000..21beec3
--- /dev/null
@@ -0,0 +1,83 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+#include <Elementary_Cursor.h>
+
+static void
+_clicked_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   elm_layout_text_set(data, "text", elm_button_label_get(obj));
+}
+
+void
+test_layout(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *box, *ly, *bt;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "layout", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Layout");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   box = elm_box_add(win);
+   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_win_resize_object_add(win, box);
+   evas_object_show(box);
+
+   ly = elm_layout_add(win);
+   elm_layout_theme_set(ly, "layout", "application", "titlebar");
+   elm_layout_label_set(ly, "Some title");
+   evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ly, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(box, ly);
+   evas_object_show(ly);
+
+   bt = elm_icon_add(win);
+   elm_icon_standard_set(bt, "chat");
+   evas_object_size_hint_min_set(bt, 20, 20);
+   elm_layout_icon_set(ly, bt);
+
+   bt = elm_icon_add(win);
+   elm_icon_standard_set(bt, "close");
+   evas_object_size_hint_min_set(bt, 20, 20);
+   elm_layout_end_set(ly, bt);
+
+   ly = elm_layout_add(win);
+   snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+   elm_layout_file_set(ly, buf, "layout");
+   evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(box, ly);
+   //elm_win_resize_object_add(win, ly);
+   evas_object_show(ly);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 1");
+   elm_layout_content_set(ly, "element1", bt);
+   evas_object_smart_callback_add(bt, "clicked", _clicked_cb, ly);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 2");
+   elm_layout_content_set(ly, "element2", bt);
+   evas_object_smart_callback_add(bt, "clicked", _clicked_cb, ly);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 3");
+   elm_layout_content_set(ly, "element3", bt);
+   evas_object_smart_callback_add(bt, "clicked", _clicked_cb, ly);
+   evas_object_show(bt);
+
+   elm_layout_part_cursor_set(ly, "text", ELM_CURSOR_WATCH);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_list.c b/src/bin/test_list.c
new file mode 100644 (file)
index 0000000..e4137e2
--- /dev/null
@@ -0,0 +1,758 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+my_show_it(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_list_item_show(data);
+}
+
+static void
+scroll_top(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Top edge!\n");
+}
+
+static void
+scroll_bottom(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Bottom edge!\n");
+}
+
+static void
+scroll_left(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Left edge!\n");
+}
+
+static void
+scroll_right(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Right edge!\n");
+}
+
+void
+test_list(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *li, *ic, *ic2, *bx, *tb2, *bt;
+   char buf[PATH_MAX];
+   Elm_List_Item *it1, *it2, *it3, *it4, *it5;
+
+   win = elm_win_add(NULL, "list", ELM_WIN_BASIC);
+   elm_win_title_set(win, "List");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   li = elm_list_add(win);
+   elm_win_resize_object_add(win, li);
+   elm_list_mode_set(li, ELM_LIST_LIMIT);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 1, 1);
+   it1 = elm_list_item_append(li, "Hello", ic, NULL,  NULL, NULL);
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_list_item_append(li, "world", ic, NULL,  NULL, NULL);
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "edit");
+   elm_icon_scale_set(ic, 0, 0);
+   elm_list_item_append(li, ".", ic, NULL,  NULL, NULL);
+
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "delete");
+   elm_icon_scale_set(ic, 0, 0);
+   ic2 = elm_icon_add(win);
+   elm_icon_standard_set(ic2, "clock");
+   elm_icon_scale_set(ic2, 0, 0);
+   it2 = elm_list_item_append(li, "How", ic, ic2,  NULL, NULL);
+
+   bx = elm_box_add(win);
+   elm_box_horizontal_set(bx, 1);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.5);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.0);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.0, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+   elm_list_item_append(li, "are", bx, NULL,  NULL, NULL);
+
+   elm_list_item_append(li, "you", NULL, NULL,  NULL, NULL);
+   it3 = elm_list_item_append(li, "doing", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "out", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "there", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "today", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "?", NULL, NULL,  NULL, NULL);
+   it4 = elm_list_item_append(li, "Here", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "are", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "some", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "more", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "items", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Is this label long enough?", NULL, NULL,  NULL, NULL);
+   it5 = elm_list_item_append(li, "Maybe this one is even longer so we can test long long items.", NULL, NULL,  NULL, NULL);
+
+   elm_list_go(li);
+
+   evas_object_show(li);
+   
+   tb2 = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, tb2);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Hello");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it1);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.5);
+   elm_table_pack(tb2, bt, 0, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "How");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it2);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.5);
+   elm_table_pack(tb2, bt, 0, 1, 1, 1);
+   evas_object_show(bt);   
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "doing");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it3);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.5);
+   elm_table_pack(tb2, bt, 0, 2, 1, 1);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Here");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it4);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.5);
+   elm_table_pack(tb2, bt, 0, 3, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Maybe this...");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it5);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.5);
+   elm_table_pack(tb2, bt, 0, 4, 1, 1);
+   evas_object_show(bt);
+
+   evas_object_show(tb2);
+   
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+
+   evas_object_smart_callback_add(li, "scroll,edge,top", scroll_top, NULL);
+   evas_object_smart_callback_add(li, "scroll,edge,bottom", scroll_bottom, NULL);
+   evas_object_smart_callback_add(li, "scroll,edge,left", scroll_left, NULL);
+   evas_object_smart_callback_add(li, "scroll,edge,right", scroll_right, NULL);
+}
+
+void
+test_list_horizontal(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *li, *ic, *ic2, *bx, *tb2, *bt;
+   char buf[PATH_MAX];
+   Elm_List_Item *it1, *it2, *it3, *it4;
+
+   win = elm_win_add(NULL, "list", ELM_WIN_BASIC);
+   elm_win_title_set(win, "List");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   li = elm_list_add(win);
+   elm_list_horizontal_set(li, EINA_TRUE);
+   elm_list_mode_set(li, ELM_LIST_LIMIT);
+   elm_win_resize_object_add(win, li);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 1, 1);
+   it1 = elm_list_item_append(li, "Hello", ic, NULL,  NULL, NULL);
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_list_item_append(li, "world", ic, NULL,  NULL, NULL);
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "edit");
+   elm_icon_scale_set(ic, 0, 0);
+   elm_list_item_append(li, ".", ic, NULL,  NULL, NULL);
+
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "delete");
+   elm_icon_scale_set(ic, 0, 0);
+   ic2 = elm_icon_add(win);
+   elm_icon_standard_set(ic2, "clock");
+   elm_icon_scale_set(ic2, 0, 0);
+   it2 = elm_list_item_append(li, "How", ic, ic2,  NULL, NULL);
+
+   bx = elm_box_add(win);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.5);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.0);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   elm_list_item_append(li, "are", bx, NULL,  NULL, NULL);
+
+   elm_list_item_append(li, "you", NULL, NULL,  NULL, NULL);
+   it3 = elm_list_item_append(li, "doing", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "out", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "there", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "today", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "?", NULL, NULL,  NULL, NULL);
+
+   it4 = elm_list_item_append(li, "And", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "here", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "we", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "are", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "done", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "with", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "items.", NULL, NULL,  NULL, NULL);
+
+   elm_list_go(li);
+
+   evas_object_show(li);
+
+   tb2 = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, tb2);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Hello");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it1);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.5, 0.9);
+   elm_table_pack(tb2, bt, 0, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "How");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it2);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.5, 0.9);
+   elm_table_pack(tb2, bt, 1, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "doing");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it3);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.5, 0.9);
+   elm_table_pack(tb2, bt, 2, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "And");
+   evas_object_smart_callback_add(bt, "clicked", my_show_it, it4);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.5, 0.9);
+   elm_table_pack(tb2, bt, 3, 0, 1, 1);
+   evas_object_show(bt);
+
+   evas_object_show(tb2);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+/***********/
+
+static void
+my_li2_clear(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_list_clear(data);
+}
+
+static void
+my_li2_sel(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_List_Item *it = elm_list_selected_item_get(obj);
+   elm_list_item_selected_set(it, 0);
+//   elm_list_item_selected_set(event_info, 0);
+}
+
+void
+test_list2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *li, *ic, *ic2, *bx, *bx2, *bt;
+   char buf[PATH_MAX];
+   Elm_List_Item *it;
+
+   win = elm_win_add(NULL, "list-2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "List 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_list_mode_set(li, ELM_LIST_LIMIT);
+//   elm_list_multi_select_set(li, 1);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   it = elm_list_item_append(li, "Hello", ic, NULL,  my_li2_sel, NULL);
+   elm_list_item_selected_set(it, 1);
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_list_item_append(li, "world", ic, NULL,  NULL, NULL);
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "edit");
+   elm_icon_scale_set(ic, 0, 0);
+   elm_list_item_append(li, ".", ic, NULL,  NULL, NULL);
+
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "delete");
+   elm_icon_scale_set(ic, 0, 0);
+   ic2 = elm_icon_add(win);
+   elm_icon_standard_set(ic2, "clock");
+   elm_icon_scale_set(ic2, 0, 0);
+   elm_list_item_append(li, "How", ic, ic2,  NULL, NULL);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.5);
+   elm_box_pack_end(bx2, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.0);
+   elm_box_pack_end(bx2, ic);
+   evas_object_show(ic);
+   elm_list_item_append(li, "are", bx2, NULL, NULL, NULL);
+
+   elm_list_item_append(li, "you", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "doing", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "out", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "there", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "today", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "?", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Here", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "are", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "some", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "more", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "items", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Longer label.", NULL, NULL,  NULL, NULL);
+
+   elm_list_go(li);
+
+   elm_box_pack_end(bx, li);
+   evas_object_show(li);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Clear");
+   evas_object_smart_callback_add(bt, "clicked", my_li2_clear, li);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+/***********/
+
+static void
+_bt_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("button was clicked\n");
+}
+
+static void
+_it_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("item was clicked\n");
+}
+
+void
+test_list3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *li, *ic, *ic2, *bx;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "list-3", ELM_WIN_BASIC);
+   elm_win_title_set(win, "List 3");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   li = elm_list_add(win);
+   elm_win_resize_object_add(win, li);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_list_mode_set(li, ELM_LIST_COMPRESS);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   ic2 = elm_button_add(win);
+   elm_button_label_set(ic2, "Click me");
+   evas_object_smart_callback_add(ic2, "clicked", _bt_clicked, NULL);
+   evas_object_propagate_events_set(ic2, 0);
+   elm_list_item_append(li, "Hello", ic, ic2,  _it_clicked, NULL);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   ic2 = elm_button_add(win);
+   elm_button_label_set(ic2, "Click me");
+   evas_object_smart_callback_add(ic2, "clicked", _bt_clicked, NULL);
+   elm_list_item_append(li, "world", ic, ic2,  _it_clicked, NULL);
+
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "edit");
+   elm_icon_scale_set(ic, 0, 0);
+   elm_list_item_append(li, ".", ic, NULL,  NULL, NULL);
+
+   ic = elm_icon_add(win);
+   elm_icon_standard_set(ic, "delete");
+   elm_icon_scale_set(ic, 0, 0);
+   ic2 = elm_icon_add(win);
+   elm_icon_standard_set(ic2, "clock");
+   elm_icon_scale_set(ic2, 0, 0);
+   elm_list_item_append(li, "How", ic, ic2,  NULL, NULL);
+
+   bx = elm_box_add(win);
+   elm_box_horizontal_set(bx, 1);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.5);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.5, 0.0);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_size_hint_align_set(ic, 0.0, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, ic);
+   evas_object_show(ic);
+
+   elm_list_item_append(li, "are", bx, NULL,  NULL, NULL);
+   elm_list_item_append(li, "you", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "doing", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "out", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "there", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "today", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "?", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Here", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "are", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "some", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "more", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "items", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Is this label long enough?", NULL, NULL,  NULL, NULL);
+   elm_list_item_append(li, "Maybe this one is even longer so we can test long long items.", NULL, NULL,  NULL, NULL);
+
+   elm_list_go(li);
+
+   evas_object_show(li);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+struct Pginfo {
+    Evas_Object *pager, *win;
+};
+
+static void
+test_list4_back_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    struct Pginfo *info = data;
+    if (!info) return;
+
+    elm_pager_content_pop(info->pager);
+}
+
+static void
+test_list4_swipe(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+    Evas_Object *box, *entry, *button;
+    struct Pginfo *info = data;
+    char *item_data;
+    if ((!event_info) || (!data)) return;
+
+    item_data = elm_list_item_data_get(event_info);
+
+    box = elm_box_add(info->win);
+    elm_box_horizontal_set(box, 0);
+    elm_box_homogenous_set(box, 0);
+    evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+    evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_show(box);
+
+    entry = elm_scrolled_entry_add(info->win);
+    elm_scrolled_entry_editable_set(entry, EINA_FALSE);
+    elm_scrolled_entry_entry_set(entry, item_data);
+    evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+    evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_show(entry);
+
+    button = elm_button_add(info->win);
+    elm_button_label_set(button, "back");
+    evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, 0);
+    evas_object_size_hint_align_set(button, EVAS_HINT_FILL, 0);
+    evas_object_smart_callback_add(button, "clicked", test_list4_back_cb, info);
+    evas_object_show(button);
+
+    elm_box_pack_start(box, entry);
+    elm_box_pack_end(box, button);
+
+    elm_pager_content_push(info->pager, box);
+}
+
+void
+test_list4(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *li, *ic, *ic2, *pager;
+   static struct Pginfo info = {NULL, NULL};
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "list-4", ELM_WIN_BASIC);
+   elm_win_title_set(win, "List 4");
+   elm_win_autodel_set(win, 1);
+   info.win = win;
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   pager = elm_pager_add(win);
+   elm_win_resize_object_add(win, pager);
+   evas_object_size_hint_weight_set(pager, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(pager, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(pager);
+   info.pager = pager;
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_list_mode_set(li, ELM_LIST_COMPRESS);
+   evas_object_smart_callback_add(li, "swipe", test_list4_swipe, &info);
+   elm_pager_content_push(pager, li);
+
+   static char pf_data[] = "Pink Floyd were formed in 1965, and originally consisted of university" \
+       "students Roger Waters, Nick Mason, Richard Wright, and Syd Barrett. The group were a popular"\
+       "fixture on London's underground music scene, and under Barrett's leadership released two "\
+       "charting singles, \"Arnold Layne\" and \"See Emily Play\", and a successful debut album, "\
+       "ThePiper at the Gates of Dawn. In 1968, guitarist and singer David Gilmour joined the "\
+       "line-up. Barrett was soon removed, due to his increasingly erratic behaviour. Following "\
+       "Barrett's departure, bass player and singer Roger Waters became the band's lyricist and "\
+       "conceptual leader, with Gilmour assuming lead guitar and much of the vocals. With this "\
+       "line-up, Floyd went on to achieve worldwide critical and commercial success with the "\
+       "conceptalbums The Dark Side of the Moon, Wish You Were Here, Animals, and The Wall.";
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/mystrale.jpg", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_list_item_append(li, "Pink Floyd", ic, NULL,  NULL, &pf_data);
+
+   static char ds_data[] = "Dire Straits were a British rock band, formed by Mark Knopfler "\
+       "(lead vocals and lead guitar), his younger brother David Knopfler (rhythm guitar and "\
+       "backing vocals), John Illsley (bass guitar and backing vocals), and Pick Withers (drums "\
+       "and percussion), and managed by Ed Bicknell, active between 1977 and 1995. Although the "\
+       "band was formed in an era when punk rock was at the forefront, Dire Straits played a more "
+       "bluesy style, albeit with a stripped-down sound that appealed to audiences weary of the "\
+       "overproduced stadium rock of the 1970s.[citation needed] In their early days, Mark and "\
+       "David requested that pub owners turn down their sound so that patrons could converse "\
+       "while the band played, an indication of their unassuming demeanor. Despite this oddly "\
+       "self-effacing approach to rock and roll, Dire Straits soon became hugely successful, with "\
+       "their first album going multi-platinum globally.";
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/mystrale_2.jpg", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_list_item_append(li, "Dire Straits", ic, NULL,  NULL, &ds_data);
+
+   static char uh_data[] = "Uriah Heep are an English hard rock band. The band released several "\
+       "commercially successful albums in the 1970s such as Uriah Heep Live (1973), but their "\
+       "audience declined by the 1980s, to the point where they became essentially a cult band in "\
+       "the United States and United Kingdom. Uriah Heep maintain a significant following in "\
+       "Germany, the Netherlands, Scandinavia, the Balkans, Japan and Russia, where they still "\
+       "perform at stadium-sized venues.";
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/icon_17.png", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 1, 1);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_list_item_append(li, "Uriah Heep", ic, NULL,  NULL, &uh_data);
+
+   static char r_data[] = "Rush is a Canadian rock band formed in August 1968, in the Willowdale "\
+       "neighbourhood of Toronto, Ontario. The band is composed of bassist, keyboardist, and lead "\
+       "vocalist Geddy Lee, guitarist Alex Lifeson, and drummer and lyricist Neil Peart. The band "\
+       "and its membership went through a number of re-configurations between 1968 and 1974, "\
+       "achieving their current form when Peart replaced original drummer John Rutsey in July 1974, "\
+       "two weeks before the group's first United States tour.";
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/icon_21.png", PACKAGE_DATA_DIR);
+   elm_icon_scale_set(ic, 0, 0);
+   elm_icon_file_set(ic, buf, NULL);
+   ic2 = elm_icon_add(win);
+   elm_icon_standard_set(ic2, "clock");
+   elm_icon_scale_set(ic2, 0, 0);
+   elm_list_item_append(li, "Rush", ic, ic2,  NULL, &r_data);
+
+   elm_list_go(li);
+
+   evas_object_show(li);
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+struct list5_data_cb {
+  Evas_Object *win, *list;
+};
+
+static void
+test_list5_item_del(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_list_item_del(data);
+}
+
+static void
+test_list5_swipe(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+    Evas_Object *button;
+    struct list5_data_cb *info = elm_list_item_data_get(event_info);
+
+    if (elm_list_item_end_get(event_info)) return;
+
+    button = elm_button_add(info->win);
+    elm_button_label_set(button, "delete");
+    evas_object_propagate_events_set(button, 0);
+    evas_object_smart_callback_add(button, "clicked", test_list5_item_del,
+                                   event_info);
+    elm_list_item_end_set(event_info, button);
+}
+
+void
+test_list5(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *li;
+   static struct list5_data_cb info;
+
+   win = elm_win_add(NULL, "list-5", ELM_WIN_BASIC);
+   elm_win_title_set(win, "List 5");
+   elm_win_autodel_set(win, 1);
+   info.win = win;
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   li = elm_list_add(win);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_list_mode_set(li, ELM_LIST_COMPRESS);
+   evas_object_smart_callback_add(li, "swipe", test_list5_swipe, NULL);
+   elm_win_resize_object_add(win, li);
+   evas_object_show(li);
+   info.list = li;
+
+   elm_list_item_append(li, "Network", NULL, NULL,  NULL, &info);
+   elm_list_item_append(li, "Audio", NULL, NULL,  NULL, &info);
+
+   elm_list_go(li);
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_map.c b/src/bin/test_map.c
new file mode 100644 (file)
index 0000000..c3a3f24
--- /dev/null
@@ -0,0 +1,604 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct Marker_Data
+{
+    const char *file;
+} Marker_Data;
+
+
+static Elm_Map_Marker_Class *itc1, *itc2, *itc_parking;
+static Elm_Map_Group_Class *itc_group1, *itc_group2, *itc_group_parking;
+
+static Evas_Object *rect;
+static int nb_elts;
+
+Marker_Data data1 = {PACKAGE_DATA_DIR"/images/logo.png"};
+Marker_Data data2 = {PACKAGE_DATA_DIR"/images/logo_small.png"};
+Marker_Data data3 = {PACKAGE_DATA_DIR"/images/panel_01.jpg"};
+Marker_Data data4 = {PACKAGE_DATA_DIR"/images/plant_01.jpg"};
+Marker_Data data5 = {PACKAGE_DATA_DIR"/images/rock_01.jpg"};
+Marker_Data data6 = {PACKAGE_DATA_DIR"/images/rock_02.jpg"};
+Marker_Data data7 = {PACKAGE_DATA_DIR"/images/sky_01.jpg"};
+Marker_Data data8 = {PACKAGE_DATA_DIR"/images/sky_02.jpg"};
+Marker_Data data9 = {PACKAGE_DATA_DIR"/images/sky_03.jpg"};
+Marker_Data data10 = {PACKAGE_DATA_DIR"/images/sky_03.jpg"};
+Marker_Data data11= {PACKAGE_DATA_DIR"/images/wood_01.jpg"};
+
+Marker_Data data_parking= {PACKAGE_DATA_DIR"/images/parking.png"};
+
+static void
+my_map_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("clicked\n");
+}
+
+static void
+my_map_press(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("press\n");
+}
+
+static void
+my_map_longpressed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("longpressed\n");
+}
+
+static void
+my_map_clicked_double(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("clicked,double\n");
+}
+
+static void
+my_map_load_detail(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("load,detail\n");
+}
+
+static void
+my_map_loaded_detail(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("loaded,detail\n");
+}
+
+static void
+my_map_zoom_start(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("zoom,start\n");
+}
+
+static void
+my_map_zoom_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("zoom,stop\n");
+}
+
+static void
+my_map_zoom_change(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("zoom,change\n");
+}
+
+static void
+my_map_anim_start(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("anim,start\n");
+}
+
+static void
+my_map_anim_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("anim,stop\n");
+}
+
+static void
+my_map_drag_start(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag,start\n");
+}
+
+static void
+my_map_drag_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag_stop\n");
+}
+
+static void
+my_map_scroll(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   double lon, lat;
+   elm_map_geo_region_get(obj, &lon, &lat);
+   printf("scroll longitude : %f latitude : %f\n", lon, lat);
+}
+
+static void
+my_map_downloaded(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   int try_num, finish_num;
+   elm_map_utils_downloading_status_get(data, &try_num, &finish_num);
+   printf("downloaded : %d / %d\n", finish_num, try_num);
+}
+
+static void
+my_bt_show_reg(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Eina_Bool b = elm_map_paused_get(data);
+   elm_map_paused_set(data, EINA_TRUE);
+   elm_map_zoom_mode_set(data, ELM_MAP_ZOOM_MODE_MANUAL);
+   elm_map_geo_region_show(data, 2.352, 48.857);
+   elm_map_zoom_set(data, 18);
+   elm_map_paused_set(data, b);
+}
+
+static void
+my_bt_bring_reg(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_geo_region_bring_in(data, 2.352, 48.857);
+}
+
+static void
+my_bt_zoom_in(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   double zoom;
+
+   zoom = elm_map_zoom_get(data);
+   zoom += 1;
+   elm_map_zoom_mode_set(data, ELM_MAP_ZOOM_MODE_MANUAL);
+   if (zoom >= (1.0 / 32.0)) elm_map_zoom_set(data, zoom);
+}
+
+static void
+my_bt_zoom_out(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   double zoom;
+
+   zoom = elm_map_zoom_get(data);
+   zoom -= 1;
+   elm_map_zoom_mode_set(data, ELM_MAP_ZOOM_MODE_MANUAL);
+   if (zoom <= 256.0) elm_map_zoom_set(data, zoom);
+}
+
+static void
+my_bt_pause(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_paused_set(data, !elm_map_paused_get(data));
+}
+
+static void
+my_bt_markers_pause(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_paused_markers_set(data, !elm_map_paused_markers_get(data));
+}
+
+static void
+my_bt_zoom_fit(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_zoom_mode_set(data, ELM_MAP_ZOOM_MODE_AUTO_FIT);
+}
+
+static void
+my_bt_zoom_fill(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_zoom_mode_set(data, ELM_MAP_ZOOM_MODE_AUTO_FILL);
+}
+
+static void
+my_bt_source_mapnik(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_source_set(data, ELM_MAP_SOURCE_MAPNIK);
+}
+
+static void
+my_bt_source_osmarender(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_source_set(data, ELM_MAP_SOURCE_OSMARENDER);
+}
+
+static void
+my_bt_source_cyclemap(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_source_set(data, ELM_MAP_SOURCE_CYCLEMAP);
+}
+
+static void
+my_bt_source_maplint(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_source_set(data, ELM_MAP_SOURCE_MAPLINT);
+}
+
+static void
+my_bt_source_module(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_source_set(data, ELM_MAP_SOURCE_MODULE);
+}
+
+static void
+my_bt_add(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    int i;
+    Elm_Map_Group_Class *g_clas;
+    Elm_Map_Marker_Class *m_clas;
+    Marker_Data *d = &data7;
+
+    for(i =0; i<1000; i++)
+    {
+        d = &data7;
+
+        int r1 = rand() % (180*2*100);
+        if(r1<=180) r1 = -r1;
+        else r1 = r1 - 180*100;
+
+        int r2 = rand() % (85*2*100);
+        if(r2<=85) r2 = -r2;
+        else r2 = r2 - 85*100;
+
+        int style = rand() % 3;
+        if(!style)
+            m_clas = itc1;
+        else if(style == 1)
+            m_clas = itc2;
+        else
+        {
+            m_clas = itc_parking;
+            d = &data_parking;
+        }
+
+       style = rand() % 2;
+       if (!style)
+         g_clas = itc_group1;
+       else
+         g_clas = itc_group2;
+
+       elm_map_marker_add(data, r1/100., r2/100., m_clas, g_clas, d); 
+    }
+    nb_elts+=1000;
+    printf("nb elements: %d\n", nb_elts);
+}
+
+static Evas_Object *
+_marker_get(Evas_Object *obj, Elm_Map_Marker *marker __UNUSED__, void *data)
+{
+    Marker_Data *d = data;
+
+    Evas_Object *bx = elm_box_add(obj);
+    evas_object_show(bx);
+
+    if(d == &data3)
+    {
+        Evas_Object *icon = elm_icon_add(obj);
+        elm_icon_file_set(icon, d->file, NULL);
+        evas_object_show(icon);
+
+        Evas_Object *o = elm_button_add(obj);
+        elm_button_icon_set(o, icon);
+        evas_object_show(o);
+        elm_box_pack_end(bx, o);
+    }
+    else
+    {
+        Evas_Object *o = evas_object_image_add(evas_object_evas_get(obj));
+        evas_object_image_file_set(o, d->file, NULL);
+        evas_object_image_filled_set(o, EINA_TRUE);
+        evas_object_size_hint_min_set(o, 64, 64);
+        evas_object_show(o);
+        elm_box_pack_end(bx, o);
+
+        Evas_Object *lbl = elm_label_add(obj);
+        elm_label_label_set(lbl, "Wolves Go !");
+        evas_object_show(lbl);
+        elm_box_pack_end(bx, lbl);
+    }
+
+    return bx;
+}
+
+static Evas_Object *
+_icon_get(Evas_Object *obj, Elm_Map_Marker *marker __UNUSED__, void *data)
+{
+    Marker_Data *d = data;
+
+    Evas_Object *icon = elm_icon_add(obj);
+    elm_icon_file_set(icon, d->file, NULL);
+    evas_object_show(icon);
+
+    return icon;
+}
+
+static Evas_Object *
+_group_icon_get(Evas_Object *obj, void *data)
+{
+    char *file = data;
+
+    Evas_Object *icon = elm_icon_add(obj);
+    elm_icon_file_set(icon, file, NULL);
+    evas_object_show(icon);
+
+    return icon;
+}
+
+static void
+_map_mouse_wheel_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Object *map = data;
+   Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info;
+   int zoom;
+   //unset the mouse wheel
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+
+   zoom = elm_map_zoom_get(map);
+
+   if (ev->z > 0)
+     zoom--;
+   else
+     zoom++;
+
+   elm_map_zoom_mode_set(map, ELM_MAP_ZOOM_MODE_MANUAL);
+   if ((zoom >= 0) && (zoom <= 18)) elm_map_zoom_set(map, zoom);
+}
+
+static void 
+_map_move_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   int x,y,w,h;
+
+   evas_object_geometry_get(data,&x,&y,&w,&h);
+   evas_object_resize(rect,w,h);
+   evas_object_move(rect,x,y);
+}
+
+void
+test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *map, *tb2, *bt, *bx;
+
+   win = elm_win_add(NULL, "map", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Map");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   map = elm_map_add(win);
+   if (map) 
+     {
+        srand( time(NULL) );
+
+        evas_object_size_hint_weight_set(map, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        elm_win_resize_object_add(win, map);
+        evas_object_data_set(map, "window", win);
+
+        //
+        itc1 = elm_map_marker_class_new(map);
+        elm_map_marker_class_get_cb_set(itc1, _marker_get);
+        elm_map_marker_class_del_cb_set(itc1, NULL);
+        itc2 = elm_map_marker_class_new(map);
+        elm_map_marker_class_get_cb_set(itc2, _marker_get);
+        elm_map_marker_class_del_cb_set(itc2, NULL);
+        elm_map_marker_class_style_set(itc2, "radio2");
+
+        itc_parking = elm_map_marker_class_new(map);
+        elm_map_marker_class_get_cb_set(itc_parking, _marker_get);
+        elm_map_marker_class_del_cb_set(itc_parking, NULL);
+        elm_map_marker_class_icon_cb_set(itc_parking, _icon_get);
+        elm_map_marker_class_style_set(itc_parking, "empty");
+        //
+
+        //
+        itc_group1 = elm_map_group_class_new(map);
+        elm_map_group_class_data_set(itc_group1, (void *)PACKAGE_DATA_DIR"/images/plant_01.jpg");
+
+        itc_group2 = elm_map_group_class_new(map);
+        elm_map_group_class_style_set(itc_group2, "radio2");
+        elm_map_group_class_zoom_displayed_set(itc_group1, 3);
+
+        itc_group_parking = elm_map_group_class_new(map);
+        elm_map_group_class_icon_cb_set(itc_group_parking, _group_icon_get);
+        elm_map_group_class_data_set(itc_group_parking, (void *)PACKAGE_DATA_DIR"/images/parking.png");
+        elm_map_group_class_style_set(itc_group_parking, "empty");
+        elm_map_group_class_zoom_displayed_set(itc_group_parking, 5);
+        //
+
+
+        rect = evas_object_rectangle_add(evas_object_evas_get(win));
+        evas_object_color_set(rect, 0, 0, 0, 0);
+        evas_object_repeat_events_set(rect,1);
+        evas_object_show(rect);
+        evas_object_event_callback_add(rect, EVAS_CALLBACK_MOUSE_WHEEL, 
+                                       _map_mouse_wheel_cb, map);
+        evas_object_raise(rect);
+
+        evas_object_event_callback_add(map, EVAS_CALLBACK_RESIZE, 
+                                       _map_move_resize_cb, map);
+        evas_object_event_callback_add(map, EVAS_CALLBACK_MOVE, 
+                                       _map_move_resize_cb, map);
+
+        elm_map_marker_add(map, 2.352, 48.857, itc1, itc_group1, &data1);
+        elm_map_marker_add(map, 2.355, 48.857, itc1, itc_group1, &data3);
+        elm_map_marker_add(map, 3, 48.857, itc2, itc_group1, &data2);
+        elm_map_marker_add(map, 2.352, 49, itc2, itc_group1, &data1);
+
+        elm_map_marker_add(map, 7.31451, 48.857127, itc1, itc_group1, &data10);
+        elm_map_marker_add(map, 7.314704, 48.857119, itc1, itc_group1, &data4);
+        elm_map_marker_add(map, 7.314704, 48.857119, itc2, itc_group1, &data5);
+        elm_map_marker_add(map, 7.31432, 48.856785, itc2, itc_group1, &data6);
+        elm_map_marker_add(map, 7.3148, 48.85725, itc1, itc_group2, &data7);
+        elm_map_marker_add(map, 7.316445, 48.8572210000694, itc1, itc_group1, &data8);
+        elm_map_marker_add(map, 7.316527000125, 48.85609, itc2, itc_group2, &data9);
+        elm_map_marker_add(map, 7.3165409990833, 48.856078, itc2, itc_group1, &data11);
+        elm_map_marker_add(map, 7.319812, 48.856561, itc2, itc_group2, &data10);
+
+        nb_elts = 13;
+
+        evas_object_smart_callback_add(map, "clicked", my_map_clicked, win);
+        evas_object_smart_callback_add(map, "press", my_map_press, win);
+        evas_object_smart_callback_add(map, "longpressed", my_map_longpressed, win);
+        evas_object_smart_callback_add(map, "clicked,double", my_map_clicked_double, win);
+        evas_object_smart_callback_add(map, "load,detail", my_map_load_detail, win);
+        evas_object_smart_callback_add(map, "loaded,detail", my_map_loaded_detail, win);
+        evas_object_smart_callback_add(map, "zoom,start", my_map_zoom_start, win);
+        evas_object_smart_callback_add(map, "zoom,stop", my_map_zoom_stop, win);
+        evas_object_smart_callback_add(map, "zoom,change", my_map_zoom_change, win);
+        evas_object_smart_callback_add(map, "scroll,anim,start", my_map_anim_start, win);
+        evas_object_smart_callback_add(map, "scroll,anim,stop", my_map_anim_stop, win);
+        evas_object_smart_callback_add(map, "scroll,drag,start", my_map_drag_start, win);
+        evas_object_smart_callback_add(map, "scroll,drag,stop", my_map_drag_stop, win);
+        evas_object_smart_callback_add(map, "scroll", my_map_scroll, win);
+        evas_object_smart_callback_add(map, "downloaded", my_map_downloaded, map);
+
+        evas_object_show(map);
+
+        tb2 = elm_table_add(win);
+        evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        elm_win_resize_object_add(win, tb2);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Z -");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_out, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.1, 0.1);
+        elm_table_pack(tb2, bt, 0, 0, 1, 1);
+        evas_object_show(bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Add 1000 markers");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_add, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.5, 0.1);
+        elm_table_pack(tb2, bt, 1, 0, 1, 1);
+        evas_object_show(bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Z +");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_in, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.9, 0.1);
+        elm_table_pack(tb2, bt, 2, 0, 1, 1);
+        evas_object_show(bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Show Paris");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_show_reg, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.1, 0.5);
+        elm_table_pack(tb2, bt, 0, 1, 1, 1);
+        evas_object_show(bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Bring Paris");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_bring_reg, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.9, 0.5);
+        elm_table_pack(tb2, bt, 2, 1, 1, 1);
+        evas_object_show(bt);
+
+        //
+        bx = elm_box_add(win);
+        evas_object_show(bx);
+        evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bx, 0.1, 0.9);
+        elm_table_pack(tb2, bx, 0, 2, 1, 1);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Pause On/Off");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_pause, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.1, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Markers pause On/Off");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_markers_pause, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.1, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+        //
+
+        //
+        bx = elm_box_add(win);
+        evas_object_show(bx);
+        evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bx, 0.5, 0.9);
+        elm_table_pack(tb2, bx, 1, 2, 1, 1);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Fit");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_fit, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.5, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Fill");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_fill, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 0.5, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+        //
+
+        //
+        bx = elm_box_add(win);
+        evas_object_show(bx);
+        evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bx, 1.0, 0.9);
+        elm_table_pack(tb2, bx, 2, 2, 1, 1);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Mapnik");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_source_mapnik, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 1.0, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Osmarender");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_source_osmarender, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 1.0, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Cycle Map");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_source_cyclemap, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 1.0, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Maplint");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_source_maplint, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 1.0, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Module");
+        evas_object_smart_callback_add(bt, "clicked", my_bt_source_module, map);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(bt, 1.0, 0.9);
+        evas_object_show(bt);
+        elm_box_pack_end(bx, bt);
+        //
+
+        evas_object_show(tb2);
+     }
+
+   evas_object_resize(win, 800, 800);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_menu.c b/src/bin/test_menu.c
new file mode 100644 (file)
index 0000000..544ad09
--- /dev/null
@@ -0,0 +1,115 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static Evas_Object *win, *bg, *menu, *rect;
+
+static void
+_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev = event_info; 
+   elm_menu_move(data, ev->canvas.x, ev->canvas.y);
+   evas_object_show(data);
+}
+
+static void 
+_populate_4(Elm_Menu_Item *item)
+{
+   Elm_Menu_Item *item2;
+
+   elm_menu_item_add(menu, item, "go-bottom", "menu 2", NULL, NULL);
+   elm_menu_item_add(menu, item, "go-first", "menu 3", NULL, NULL);
+   elm_menu_item_separator_add(menu, item);
+   item2 = elm_menu_item_add(menu, item, "go-last", "Disabled item", NULL, NULL);
+   elm_menu_item_disabled_set(item2, 1);
+   item2 = elm_menu_item_add(menu, item, "go-next", "Disabled item", NULL, NULL);
+   elm_menu_item_disabled_set(item2, 1);
+   item2 = elm_menu_item_add(menu, item, "go-up", "Disabled item", NULL, NULL);
+   elm_menu_item_disabled_set(item2, 1);
+}
+
+static void 
+_populate_3(Elm_Menu_Item *item)
+{
+   Elm_Menu_Item *item2;
+
+   elm_menu_item_add(menu, item, "media-eject", "menu 2", NULL, NULL);
+   elm_menu_item_add(menu, item, "media-playback-start", "menu 3", NULL, NULL);
+   elm_menu_item_separator_add(menu,item);
+   item2 = elm_menu_item_add(menu, item, "media-playback-stop", "Disabled item", NULL, NULL);
+   elm_menu_item_disabled_set(item2, 1);
+}
+
+static void 
+_populate_2(Elm_Menu_Item *item)
+{
+   Elm_Menu_Item *item2, *item3;
+
+   elm_menu_item_add(menu, item, "system-reboot", "menu 2", NULL, NULL);
+   item2 = elm_menu_item_add(menu, item, "system-shutdown", "menu 3", NULL, NULL);
+   
+   _populate_3(item2);
+
+   elm_menu_item_separator_add(menu,item);
+   elm_menu_item_separator_add(menu,item);
+   elm_menu_item_separator_add(menu,item);
+   elm_menu_item_separator_add(menu,item);
+   elm_menu_item_separator_add(menu,item);
+   elm_menu_item_separator_add(menu,item);
+   elm_menu_item_separator_add(menu,item);
+
+   item2 = elm_menu_item_add(menu, item, "system-lock-screen", "menu 2", NULL, NULL);
+   elm_menu_item_separator_add(menu,item);
+
+   item3 = elm_menu_item_add(menu, item, "system-run", "Disabled item", NULL, NULL);
+   elm_menu_item_disabled_set(item3, 1);
+
+   _populate_4(item2);
+}
+
+static void 
+_populate_1(Elm_Menu_Item *item)
+{
+   Elm_Menu_Item *item2;
+
+   item2 = elm_menu_item_add(menu, item, "object-rotate-left", "menu 1", NULL, NULL);
+
+   _populate_2(item2);
+}
+
+void
+test_menu(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Menu_Item *item;
+
+   win = elm_win_add(NULL, "Menu", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Menu");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   rect = evas_object_rectangle_add(evas_object_evas_get(win));
+   elm_win_resize_object_add(win, rect);
+   evas_object_color_set(rect, 0, 0, 0, 0);
+   evas_object_show(rect);
+
+   menu = elm_menu_add(win);
+   elm_menu_item_add(menu, NULL, NULL, "first item", NULL, NULL);
+
+   item = elm_menu_item_add(menu, NULL, "mail-reply-all", "second item", NULL, NULL);
+   _populate_1(item);
+
+   elm_menu_item_add(menu, item, "window-new", "sub menu", NULL, NULL);
+
+   evas_object_event_callback_add(rect, EVAS_CALLBACK_MOUSE_DOWN, _show, menu);
+
+   evas_object_resize(win, 350, 200);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_multi.c b/src/bin/test_multi.c
new file mode 100644 (file)
index 0000000..45fe59d
--- /dev/null
@@ -0,0 +1,135 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+#define IND_NUM 20
+
+static Evas_Object *indicator[IND_NUM];
+
+static void
+_mouse_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev = event_info;
+
+   if (ev->button != 1) return;
+   printf("MOUSE: down @ %4i %4i\n", ev->canvas.x, ev->canvas.y);
+   evas_object_move(indicator[0], ev->canvas.x, ev->canvas.y);
+   evas_object_resize(indicator[0], 1, 1);
+   evas_object_show(indicator[0]);
+}
+
+static void
+_mouse_up(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Up *ev = event_info;
+   if (ev->button != 1) return;
+   printf("MOUSE: up   @ %4i %4i\n", ev->canvas.x, ev->canvas.y);
+   evas_object_hide(indicator[0]);
+}
+
+static void
+_mouse_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Move *ev = event_info;
+   printf("MOUSE: move @ %4i %4i\n", ev->cur.canvas.x, ev->cur.canvas.y);
+   evas_object_move(indicator[0], ev->cur.canvas.x, ev->cur.canvas.y);
+   evas_object_resize(indicator[0], 1, 1);
+}
+
+static void
+_multi_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Evas_Event_Multi_Down *ev = event_info;
+   printf("MULTI: down @ %4i %4i | dev: %i\n", ev->canvas.x, ev->canvas.y, ev->device);
+   if (ev->device >= IND_NUM) return;
+   evas_object_move(indicator[ev->device], ev->canvas.x, ev->canvas.y);
+   evas_object_resize(indicator[ev->device], 1, 1);
+   evas_object_show(indicator[ev->device]);
+}
+
+static void
+_multi_up(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Evas_Event_Multi_Up *ev = event_info;
+   printf("MULTI: up    @ %4i %4i | dev: %i\n", ev->canvas.x, ev->canvas.y, ev->device);
+   if (ev->device >= IND_NUM) return;
+   evas_object_hide(indicator[ev->device]);
+}
+
+static void
+_multi_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Evas_Event_Multi_Move *ev = event_info;
+   printf("MULTI: move @ %4i %4i | dev: %i\n", ev->cur.canvas.x,
+          ev->cur.canvas.y, ev->device);
+   if (ev->device >= IND_NUM) return;
+   evas_object_move(indicator[ev->device], ev->cur.canvas.x, ev->cur.canvas.y);
+   evas_object_resize(indicator[ev->device], 1, 1);
+}
+
+void
+my_bt_rot(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   elm_win_rotation_set(win, elm_win_rotation_get(win) + 90);
+}
+
+void
+test_multi(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *r, *bx, *bt;
+   int i;
+
+   win = elm_win_add(NULL, "bg-plain", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Bg Plain");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   r = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_size_hint_weight_set(r, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_color_set(r, 0, 0, 0, 0);
+   elm_win_resize_object_add(win, r);
+   evas_object_show(r);
+
+   for (i = 0; i < IND_NUM; i++)
+     {
+        char buf[PATH_MAX];
+
+        snprintf(buf, sizeof(buf), "%s/objects/multip.edj", PACKAGE_DATA_DIR);
+        indicator[i] = edje_object_add(evas_object_evas_get(win));
+        edje_object_file_set(indicator[i], buf, "point");
+     }
+
+   evas_object_event_callback_add(r, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, win);
+   evas_object_event_callback_add(r, EVAS_CALLBACK_MOUSE_UP, _mouse_up, win);
+   evas_object_event_callback_add(r, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, win);
+   evas_object_event_callback_add(r, EVAS_CALLBACK_MULTI_DOWN, _multi_down, win);
+   evas_object_event_callback_add(r, EVAS_CALLBACK_MULTI_UP, _multi_up, win);
+   evas_object_event_callback_add(r, EVAS_CALLBACK_MULTI_MOVE, _multi_move, win);
+   
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rotate");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_rot, win);
+   evas_object_size_hint_align_set(bt, 0.0, 0.0);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   
+   evas_object_size_hint_min_set(bg, 160, 160);
+   evas_object_resize(win, 480, 800);
+
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_notify.c b/src/bin/test_notify.c
new file mode 100644 (file)
index 0000000..bd107ad
--- /dev/null
@@ -0,0 +1,307 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void
+_bt(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *notify = data;
+   evas_object_show(notify);
+}
+
+static void
+_bt_close(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *notify = data;
+   evas_object_hide(notify);
+}
+
+static void
+_bt_timer_close(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *notify = data;
+   elm_notify_timeout_set(notify, 2.0);
+}
+
+static void
+_notify_timeout(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Notify timed out!\n");
+}
+
+static void
+_notify_block(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("Notify block area clicked!!\n");
+}
+
+void
+test_notify(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *tb, *notify, *bt, *lb;
+
+   win = elm_win_add(NULL, "Notify", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Notify");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   tb = elm_table_add(win);
+   elm_win_resize_object_add(win, tb);
+   evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(tb);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "This position is the default.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 1, 0, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   elm_notify_repeat_events_set(notify, EINA_FALSE);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM);
+   elm_notify_timeout_set(notify, 5.0);
+   evas_object_smart_callback_add(notify, "timeout", _notify_timeout, NULL);
+   evas_object_smart_callback_add(notify, "block,clicked", _notify_block, NULL);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Bottom position. This notify use a timeout of 5 sec.<br>"
+        "<b>The events outside the window are blocked.</b>");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Bottom");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 1, 2, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_LEFT);
+   elm_notify_timeout_set(notify, 10.0);
+   evas_object_smart_callback_add(notify, "timeout", _notify_timeout, NULL);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Left position. This notify use a timeout of 10 sec.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Left");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 0, 1, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_CENTER);
+   elm_notify_timeout_set(notify, 10);
+   elm_notify_timeout_set(notify, 10.0);
+   evas_object_smart_callback_add(notify, "timeout", _notify_timeout, NULL);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Center position. This notify use a timeout of 10 sec.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Center");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 1, 1, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_RIGHT);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Right position.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Right");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 2, 1, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_TOP_LEFT);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Top Left position.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top Left");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 0, 0, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_TOP_RIGHT);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Top Right position.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Top Right");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 2, 0, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM_LEFT);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Bottom Left position.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _bt_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Bottom Left");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 0, 2, 1, 1);
+   evas_object_show(bt);
+
+   notify = elm_notify_add(win);
+   evas_object_size_hint_weight_set(notify, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM_RIGHT);
+
+   bx = elm_box_add(win);
+   elm_notify_content_set(notify, bx);
+   elm_box_horizontal_set(bx, 1);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb, "Bottom Right position.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close in 2s");
+   evas_object_smart_callback_add(bt, "clicked", _bt_timer_close, notify);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Bottom Right");
+   evas_object_smart_callback_add(bt, "clicked", _bt, notify);
+   elm_table_pack(tb, bt, 2, 2, 1, 1);
+   evas_object_show(bt);
+
+   evas_object_show(win);
+   evas_object_resize(win, 300, 350);
+}
+
+#endif
+
diff --git a/src/bin/test_pager.c b/src/bin/test_pager.c
new file mode 100644 (file)
index 0000000..3324da6
--- /dev/null
@@ -0,0 +1,330 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+typedef struct _Pginfo Pginfo;
+
+struct _Pginfo
+{
+    Evas_Object *win, *pager, *pg1, *pg2, *pg3, *pg4;
+};
+
+static void
+my_pager_1(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Pginfo *info = data;
+   elm_pager_content_promote(info->pager, info->pg2);
+}
+
+static void
+my_pager_2(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Pginfo *info = data;
+   elm_pager_content_promote(info->pager, info->pg3);
+}
+
+static void
+my_pager_3(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Pginfo *info = data;
+   elm_pager_content_promote(info->pager, info->pg4);
+}
+
+
+static void
+my_pager_4(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Pginfo *info = data;
+   elm_pager_content_promote(info->pager, info->pg1);
+}
+
+
+static void
+my_pager_pop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Pginfo *info = data;
+   elm_pager_content_pop(info->pager);
+}
+
+struct style_tuple {
+     const char *label;
+     const char *name;
+};
+static const struct style_tuple styles[] = {
+       { "Default", "default"},
+       { "Slide", "slide"},
+       { "Slide Invisible", "slide_invisible"},
+       { "Fade", "fade"},
+       { "Fade Translucide", "fade_translucide"},
+       { "Fade Invisible", "fade_invisible"},
+       { "Flip", "flip"},
+};
+
+static void
+_style(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *pg = data;
+   elm_object_style_set(pg, styles[elm_radio_value_get(obj)].name);
+}
+
+void
+test_pager(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *pg, *bx, *lb, *bt;
+   static Pginfo info;
+
+   win = elm_win_add(NULL, "pager", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Pager");
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+   elm_win_autodel_set(win, 1);
+   info.win = win;
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   pg = elm_pager_add(win);
+   evas_object_size_hint_weight_set(pg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, pg);
+   evas_object_show(pg);
+
+   info.pager = pg;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "This is page 1 in a pager stack.<br>"
+                      "<br>"
+                      "So what is a pager stack? It is a stack<br>"
+                      "of pages that hold widgets in it. The<br>"
+                      "pages can be pushed and popped on and<br>"
+                      "off the stack, activated and otherwise<br>"
+                      "activated if already in the stack<br>"
+                      "(activated means promoted to the top of<br>"
+                      "the stack).<br>"
+                      "<br>"
+                      "The theme may define the animation how<br>"
+                      "show and hide of pages. Select one theme style:");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   unsigned int i = 0;
+   Evas_Object *rdg = NULL, *rd;
+   for (i = 0; i < (sizeof(styles) / sizeof(struct style_tuple)); i++)
+     {
+        rd = elm_radio_add(win);
+        elm_radio_label_set(rd, styles[i].label);
+        elm_radio_state_value_set(rd, i);
+        if (rdg)
+          elm_radio_group_add(rd, rdg);
+        else
+          rdg = rd;
+        evas_object_smart_callback_add(rd, "changed", _style, pg);
+        elm_box_pack_end(bx, rd);
+        evas_object_show(rd);
+     }
+   elm_radio_value_set(rd, 0);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Flip to 2");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_1, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Popme");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_pop, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   elm_pager_content_push(pg, bx);
+   info.pg1 = bx;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "This is page 2 in a pager stack.<br>"
+                      "<br>"
+                      "This is just like the previous page in<br>"
+                      "the pager stack."
+                      );
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Flip to 3");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_2, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Popme");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_pop, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   elm_pager_content_push(pg, bx);
+   info.pg2 = bx;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "This is page 3 in a pager stack.<br>"
+                      "<br>"
+                      "This is just like the previous page in<br>"
+                      "the pager stack.");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Flip to 1");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_3, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Popme");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_pop, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   elm_pager_content_push(pg, bx);
+   info.pg3 = bx;
+
+   Evas_Object *ly, *ly2;
+   char buf[4096];
+   
+   ly = elm_layout_add(win);
+   snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+   elm_layout_file_set(ly, buf, "test/layout");
+   evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(ly);
+
+   ly2 = elm_layout_add(win);
+   snprintf(buf, sizeof(buf), "%s/objects/test.edj", PACKAGE_DATA_DIR);
+   elm_layout_file_set(ly2, buf, "layout2");
+   evas_object_size_hint_weight_set(ly2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   //elm_win_resize_object_add(win, ly2);
+   evas_object_show(ly2);
+
+   
+
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Flip to 1");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_4, &info);
+   elm_layout_content_set(ly2, "element1", bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Popme");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_pop, &info);
+   evas_object_show(bt);
+   elm_layout_content_set(ly2, "element2", bt);
+
+   elm_layout_content_set(ly, "swallow", ly2);
+   evas_object_show(ly);
+
+   elm_pager_content_push(pg, ly);
+   info.pg4 = ly2;
+
+
+   evas_object_show(win);
+}
+
+static void
+my_pager_push(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Pginfo *info = data;
+   Evas_Object *bx, *bt, *lb;
+   static int count = 2;
+   char buf[32];
+
+   bx = elm_box_add(info->win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   lb = elm_label_add(info->win);
+   snprintf(buf, sizeof(buf), "This is page %d in the slide pager<br><br>", count++);
+   elm_label_label_set(lb, buf);
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(info->win);
+   elm_button_label_set(bt, "Push a new page");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_push, info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(info->win);
+   elm_button_label_set(bt, "Go back (pop)");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_pop, info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   elm_pager_content_push(info->pager, bx);
+}
+
+void
+test_pager_slide(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *pg, *bx, *lb, *bt;
+   static Pginfo info;
+
+   win = elm_win_add(NULL, "pager", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Pager Slide");
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+   elm_win_autodel_set(win, 1);
+   info.win = win;
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   pg = elm_pager_add(win);
+   elm_win_resize_object_add(win, pg);
+   elm_object_style_set(pg, "slide");
+   evas_object_show(pg);
+   info.pager = pg;
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "This is page 1 in a slide pager.<br>"
+                      "<br>"
+                      "The slide pager style is useful for browsing<br>"
+                      "a hierarchy of objects, as it makes clear<br>"
+                      "the direction of the browse.<br>"
+                      "This is the 'slide' style, also available<br>"
+                      "a fully transparent style named 'slide_invisble'.<br>"
+                      "<br>");
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Push a new page");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_push, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Go back (pop)");
+   evas_object_smart_callback_add(bt, "clicked", my_pager_pop, &info);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   elm_pager_content_push(pg, bx);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_panel.c b/src/bin/test_panel.c
new file mode 100644 (file)
index 0000000..aa0493a
--- /dev/null
@@ -0,0 +1,264 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static Elm_Genlist_Item_Class itc;
+
+static void _bstatus(void *data, Evas_Object *obj, void *event_info);
+static void _tstatus(void *data, Evas_Object *obj, void *event_info);
+static char *_label_get(void *data, Evas_Object *obj, const char *source);
+static Evas_Object *_icon_get(void *data, Evas_Object *obj, const char *source);
+static Eina_Bool _state_get(void *data, Evas_Object *obj, const char *source);
+static void _item_del(void *data, Evas_Object *obj);
+static void _fill_list(Evas_Object *obj);
+static Eina_Bool _dir_has_subs(const char *path);
+
+static void
+_tstatus(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Toolbar_Item *sel;
+   const char *status;
+
+   if (elm_panel_hidden_get((Evas_Object*)data))
+     status = "hidden";
+   else
+     status = "shown";
+   printf("The top panel is currently %s\n", status);
+   sel = elm_toolbar_selected_item_get(obj);
+   elm_toolbar_item_selected_set(sel, EINA_FALSE);
+}
+
+static void
+_bstatus(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Toolbar_Item *sel;
+   const char *status;
+
+   if (elm_panel_hidden_get((Evas_Object*)data))
+     status = "hidden";
+   else
+     status = "shown";
+   printf("The bottom panel is currently %s\n", status);
+   sel = elm_toolbar_selected_item_get(obj);
+   elm_toolbar_item_selected_set(sel, EINA_FALSE);
+}
+
+static char *
+_label_get(void *data, Evas_Object *obj __UNUSED__, const char *source __UNUSED__) 
+{
+   return strdup(ecore_file_file_get(data));
+}
+
+static Evas_Object *
+_icon_get(void *data, Evas_Object *obj, const char *source) 
+{
+   if (!strcmp(source, "elm.swallow.icon")) 
+     {
+        Evas_Object *ic;
+
+        ic = elm_icon_add(obj);
+        if (ecore_file_is_dir((char *)data))
+          elm_icon_standard_set(ic, "folder");
+        else
+          elm_icon_standard_set(ic, "file");
+        evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+        evas_object_show(ic);
+        return ic;
+     }
+   return NULL;
+}
+
+static Eina_Bool 
+_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *source __UNUSED__) 
+{
+   return EINA_FALSE;
+}
+
+static void 
+_item_del(void *data, Evas_Object *obj __UNUSED__) 
+{
+   eina_stringshare_del(data);
+}
+
+static void 
+_fill_list(Evas_Object *obj) 
+{
+   DIR *d;
+   struct dirent *de;
+   Eina_List *dirs = NULL, *l;
+   char *real;
+
+   if (!(d = opendir(getenv("HOME")))) return;
+   while ((de = readdir(d))) 
+     {
+        char buff[PATH_MAX];
+
+        if (de->d_name[0] == '.') continue;
+        snprintf(buff, sizeof(buff), "%s/%s", getenv("HOME"), de->d_name);
+        if (!ecore_file_is_dir(buff)) continue;
+        real = ecore_file_realpath(buff);
+        dirs = eina_list_append(dirs, real);
+     }
+   closedir(d);
+
+   dirs = eina_list_sort(dirs, eina_list_count(dirs), EINA_COMPARE_CB(strcoll));
+
+   EINA_LIST_FOREACH(dirs, l, real) 
+     {
+        Eina_Bool result = EINA_FALSE;
+
+        result = _dir_has_subs(real);
+        if (!result) 
+          elm_genlist_item_append(obj, &itc, eina_stringshare_add(real), 
+                                  NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+        else 
+          elm_genlist_item_append(obj, &itc, eina_stringshare_add(real), 
+                                  NULL, ELM_GENLIST_ITEM_SUBITEMS, 
+                                  NULL, NULL);
+        free(real);
+     }
+   eina_list_free(dirs);
+}
+
+static Eina_Bool 
+_dir_has_subs(const char *path) 
+{
+   DIR *d;
+   struct dirent *de;
+   Eina_Bool result = EINA_FALSE;
+
+   if (!path) return result;
+   if (!(d = opendir(path))) return result;
+   while ((de = readdir(d))) 
+     {
+        char buff[PATH_MAX];
+
+        if (de->d_name[0] == '.') continue;
+        snprintf(buff, sizeof(buff), "%s/%s", path, de->d_name);
+        if (ecore_file_is_dir(buff)) 
+          {
+             result = EINA_TRUE;
+             break;
+          }
+     }
+   closedir(d);
+   return result;
+}
+
+void
+test_panel(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *panel, *bx, *vbx, *toolbar;
+   Evas_Object *list;
+
+   win = elm_win_add(NULL, "panel", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Panel");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   vbx = elm_box_add(win);
+   elm_win_resize_object_add(win, vbx);
+   evas_object_size_hint_weight_set(vbx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(vbx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(vbx);
+
+   bx = elm_box_add(win);
+   elm_box_horizontal_set(bx, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(bx);
+
+   panel = elm_panel_add(win);
+   elm_panel_orient_set(panel, ELM_PANEL_ORIENT_TOP);
+   evas_object_size_hint_weight_set(panel, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(panel, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   toolbar = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(toolbar, 0);
+   elm_toolbar_mode_shrink_set(toolbar, ELM_TOOLBAR_SHRINK_NONE);
+   evas_object_size_hint_weight_set(toolbar, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(toolbar, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(toolbar);
+
+   elm_toolbar_item_append(toolbar, "home", "Hello", _tstatus, panel);
+
+   elm_panel_content_set(panel, toolbar);
+   elm_box_pack_end(vbx, panel);
+   evas_object_show(panel);
+
+   panel = elm_panel_add(win);
+   elm_panel_orient_set(panel, ELM_PANEL_ORIENT_LEFT);
+   evas_object_size_hint_weight_set(panel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(panel, 0, EVAS_HINT_FILL);
+
+   itc.item_style = "default";
+   itc.func.label_get = _label_get;
+   itc.func.icon_get = _icon_get;
+   itc.func.state_get = _state_get;
+   itc.func.del = _item_del;
+
+   list = elm_genlist_add(win);
+   evas_object_size_hint_min_set(list, 100, -1);
+   evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(list);
+
+   elm_panel_content_set(panel, list);
+
+   elm_box_pack_end(bx, panel);
+   evas_object_show(panel);
+
+   _fill_list(list);
+
+   panel = elm_panel_add(win);
+   elm_panel_orient_set(panel, ELM_PANEL_ORIENT_RIGHT);
+   evas_object_size_hint_weight_set(panel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(panel, 1, EVAS_HINT_FILL);
+   elm_panel_hidden_set(panel, EINA_TRUE);
+
+   list = elm_genlist_add(win);
+   evas_object_size_hint_min_set(list, 100, -1);
+   evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(list);
+
+   elm_panel_content_set(panel, list);
+
+   elm_box_pack_end(bx, panel);
+   evas_object_show(panel);
+
+   _fill_list(list);
+
+   elm_box_pack_end(vbx, bx);
+
+   panel = elm_panel_add(win);
+   elm_panel_orient_set(panel, ELM_PANEL_ORIENT_BOTTOM);
+   evas_object_size_hint_weight_set(panel, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(panel, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_panel_hidden_set(panel, EINA_TRUE);
+
+   toolbar = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(toolbar, 0);
+   elm_toolbar_mode_shrink_set(toolbar, ELM_TOOLBAR_SHRINK_NONE);
+   evas_object_size_hint_weight_set(toolbar, EVAS_HINT_EXPAND, 0);
+   evas_object_size_hint_align_set(toolbar, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(toolbar);
+
+   elm_toolbar_item_append(toolbar, "home", "Hello", _bstatus, panel);
+
+   elm_panel_content_set(panel, toolbar);
+   elm_box_pack_end(vbx, panel);
+   evas_object_show(panel);
+
+   evas_object_resize(win, 320, 400);
+   evas_object_show(win);
+}
+
+
+#endif
diff --git a/src/bin/test_panes.c b/src/bin/test_panes.c
new file mode 100644 (file)
index 0000000..b0800d6
--- /dev/null
@@ -0,0 +1,118 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static double size = 0.0;
+
+static void
+_press(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    printf("press\n");
+}
+
+static void
+_unpress(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+    printf("unpress, size : %f\n", elm_panes_content_left_size_get(obj));
+}
+
+static void
+_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    printf("clicked\n");
+}
+
+
+static void
+_clicked_double(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+    printf("clicked double\n");
+    if(elm_panes_content_left_size_get(obj) > 0)
+    {
+        size = elm_panes_content_left_size_get(obj);
+        elm_panes_content_left_size_set(obj, 0.0);
+    }
+    else
+        elm_panes_content_left_size_set(obj, size);
+}
+
+
+void
+test_panes(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *panes, *panes_h, *bt;
+
+   win = elm_win_add(NULL, "panes", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Panes");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+   evas_object_show(bg);
+
+   panes = elm_panes_add(win);
+   elm_win_resize_object_add(win, panes);
+   evas_object_size_hint_weight_set(panes, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(panes, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(panes);
+
+   evas_object_smart_callback_add(panes, "clicked", _clicked, panes);
+   evas_object_smart_callback_add(panes, "clicked,double", _clicked_double, panes);
+
+   evas_object_smart_callback_add(panes, "press", _press, panes);
+   evas_object_smart_callback_add(panes, "unpress", _unpress, panes);
+
+
+   //
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Left");
+   evas_object_size_hint_weight_set(bt, 1.0, 1.0);
+   evas_object_size_hint_align_set(bt, -1.0, -1.0);
+   evas_object_show(bt);
+   elm_panes_content_left_set(panes, bt);
+   //
+
+   //
+   panes_h = elm_panes_add(win);
+   elm_panes_horizontal_set(panes_h, EINA_TRUE);
+   evas_object_size_hint_weight_set(panes_h, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(panes_h, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(panes_h);
+
+   evas_object_smart_callback_add(panes_h, "clicked", _clicked, panes_h);
+   evas_object_smart_callback_add(panes_h, "clicked,double", _clicked_double, panes_h);
+
+   evas_object_smart_callback_add(panes_h, "press", _press, panes_h);
+   evas_object_smart_callback_add(panes_h, "unpress", _unpress, panes_h);
+   elm_panes_content_right_set(panes, panes_h);
+   //
+
+   //
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Up");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(bt);
+   elm_panes_content_left_set(panes_h, bt);
+   //
+
+   //
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Down");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(bt);
+   elm_panes_content_right_set(panes_h, bt);
+   //
+
+
+   evas_object_resize(win, 320, 400);
+   evas_object_show(win);
+}
+
+
+#endif
diff --git a/src/bin/test_photo.c b/src/bin/test_photo.c
new file mode 100644 (file)
index 0000000..1658f30
--- /dev/null
@@ -0,0 +1,104 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static void drop_cb(void *mydata, Evas_Object *obj, void *evdata);
+static void drag_stop_cb(void *mydata, Evas_Object *obj, void *evdata);
+static void drag_start_cb(void *mydata, Evas_Object *obj, void *evdata);
+
+void
+test_photo(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *sc, *tb, *ph;
+   int i, j, n;
+   char buf[PATH_MAX];
+   const char *img[9] =
+     {
+        "panel_01.jpg",
+          "mystrale.jpg",
+          "mystrale_2.jpg",
+          "rock_02.jpg",
+          "sky_01.jpg",
+          "sky_02.jpg",
+          "sky_03.jpg",
+          "sky_04.jpg",
+          "wood_01.jpg"
+     };
+
+   win = elm_win_add(NULL, "photo", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Photo");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   tb = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   
+   n = 0;
+   for (j = 0; j < 12; j++)
+     {
+        for (i = 0; i < 12; i++)
+          {
+             ph = elm_photo_add(win);
+             snprintf(buf, sizeof(buf), "%s/images/%s",
+                      PACKAGE_DATA_DIR, img[n]);
+             n++;
+             if (n >= 9) n = 0;
+             elm_photo_size_set(ph, 80);
+             elm_photo_file_set(ph, buf);
+            elm_photo_editable_set(ph, 1);
+             evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND,
+                                              EVAS_HINT_EXPAND);
+             evas_object_size_hint_align_set(ph, EVAS_HINT_FILL,
+                                             EVAS_HINT_FILL);
+            evas_object_smart_callback_add(ph, "drop",
+                                            drop_cb, NULL);
+             evas_object_smart_callback_add(ph, "drag,start",
+                                            drag_start_cb, NULL);
+             evas_object_smart_callback_add(ph, "drag,stop",
+                                            drag_stop_cb, NULL);
+
+             if((n == 2) || (n == 3)) {
+                elm_photo_fill_inside_set(ph, EINA_TRUE);
+                elm_object_style_set(ph, "shadow");
+             }
+             elm_table_pack(tb, ph, i, j, 1, 1);
+             evas_object_show(ph);
+          }
+     }
+   
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, sc);
+   
+   elm_scroller_content_set(sc, tb);
+   evas_object_show(tb);
+   evas_object_show(sc);
+
+   evas_object_resize(win, 300, 300);
+   evas_object_show(win);
+}
+
+/* Never called, elm_photo never call "drop" smart cb */
+static void
+drop_cb(void *mydata __UNUSED__, Evas_Object *obj, void *evdata __UNUSED__){
+   printf("Drop on obj %p\n", obj);
+}
+
+static void
+drag_start_cb(void *mydata __UNUSED__, Evas_Object *obj __UNUSED__, void *evdata __UNUSED__){
+   
+}
+
+static void
+drag_stop_cb(void *mydata __UNUSED__, Evas_Object *obj __UNUSED__, void *evdata __UNUSED__){
+
+}
+
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
+#endif
diff --git a/src/bin/test_photocam.c b/src/bin/test_photocam.c
new file mode 100644 (file)
index 0000000..97891f5
--- /dev/null
@@ -0,0 +1,342 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static Evas_Object *rect;
+
+static void
+my_ph_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("clicked\n");
+}
+
+static void
+my_ph_press(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("press\n");
+}
+
+static void
+my_ph_longpressed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("longpressed\n");
+}
+
+static void
+my_ph_clicked_double(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("clicked,double\n");
+}
+
+static void
+my_ph_load(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("load\n");
+}
+
+static void
+my_ph_loaded(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("loaded\n");
+}
+
+static void
+my_ph_load_details(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("load,details\n");
+}
+
+static void
+my_ph_loaded_details(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("loaded,details\n");
+}
+
+static void
+my_ph_zoom_start(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("zoom,start\n");
+}
+
+static void
+my_ph_zoom_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("zoom,stop\n");
+}
+
+static void
+my_ph_zoom_change(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("zoom,change\n");
+}
+
+static void
+my_ph_anim_start(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("anim,start\n");
+}
+
+static void
+my_ph_anim_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("anim,stop\n");
+}
+
+static void
+my_ph_drag_start(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag,start\n");
+}
+
+static void
+my_ph_drag_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("drag_stop\n");
+}
+
+static void
+my_ph_scroll(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   int x, y, w, h;
+   elm_photocam_region_get(obj, &x, &y, &w, &h);
+   printf("scroll %i %i %ix%i\n", x, y, w, h);
+}
+
+static void
+my_bt_open(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Object *ph = data;
+   const char *file = event_info;
+
+   if (file)
+     elm_photocam_file_set(ph, file);
+}
+
+static void
+my_bt_show_reg(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_photocam_image_region_show(data, 30, 50, 500, 300);
+}
+
+static void
+my_bt_bring_reg(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+
+{
+   elm_photocam_image_region_bring_in(data, 800, 300, 500, 300);
+}
+
+static void
+my_bt_zoom_in(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   double zoom;
+
+   zoom = elm_photocam_zoom_get(data);
+   zoom -= 0.5;
+   elm_photocam_zoom_mode_set(data, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
+   if (zoom >= (1.0 / 32.0)) elm_photocam_zoom_set(data, zoom);
+}
+
+static void
+my_bt_zoom_out(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   double zoom;
+
+   zoom = elm_photocam_zoom_get(data);
+   zoom += 0.5;
+   elm_photocam_zoom_mode_set(data, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
+   if (zoom <= 256.0) elm_photocam_zoom_set(data, zoom);
+}
+
+static void
+my_bt_pause(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_photocam_paused_set(data, !elm_photocam_paused_get(data));
+}
+
+static void
+my_bt_zoom_fit(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_photocam_zoom_mode_set(data, ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT);
+}
+
+static void
+my_bt_zoom_fill(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_photocam_zoom_mode_set(data, ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL);
+}
+
+static void
+_photocam_mouse_wheel_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Object *photocam = data;
+   Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info;
+   int zoom;
+   double val;
+   //unset the mouse wheel
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+
+   zoom = elm_photocam_zoom_get(photocam);
+   if ((ev->z>0) && (zoom == 1)) return;
+
+   if (ev->z > 0)
+     zoom /= 2;
+   else
+     zoom *= 2;
+
+   val = 1;
+   int _zoom = zoom;
+   while(_zoom>1)
+     {
+       _zoom /= 2;
+       val++;
+     }
+
+   elm_photocam_zoom_mode_set(photocam, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
+   if (zoom >= 1) elm_photocam_zoom_set(photocam, zoom);
+}
+
+static void
+_photocam_move_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   int x,y,w,h;
+
+   evas_object_geometry_get(data,&x,&y,&w,&h);
+   evas_object_resize(rect,w,h);
+   evas_object_move(rect,x,y);
+}
+
+void
+test_photocam(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *ph, *tb2, *bt;
+   // these were just testing - use the "select photo" browser to select one
+   const char *img[5] =
+     {
+        "/home/raster/t1.jpg",  //   5 mpixel
+        "/home/raster/t2.jpg",  //  18 mpixel
+        "/home/raster/t3.jpg",  //  39 mpixel
+        "/home/raster/t4.jpg",  // 192 mpixel
+        "/home/raster/t5.jpg"   // 466 mpixel
+     };
+
+   win = elm_win_add(NULL, "photocam", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Photocam");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   ph = elm_photocam_add(win);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, ph);
+   evas_object_data_set(ph, "window", win);
+
+   rect = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_color_set(rect, 0, 0, 0, 0);
+   evas_object_repeat_events_set(rect,1);
+   evas_object_show(rect);
+   evas_object_event_callback_add(rect, EVAS_CALLBACK_MOUSE_WHEEL, _photocam_mouse_wheel_cb, ph);
+   evas_object_raise(rect);
+
+   evas_object_event_callback_add(ph, EVAS_CALLBACK_RESIZE, _photocam_move_resize_cb, ph);
+   evas_object_event_callback_add(ph, EVAS_CALLBACK_MOVE, _photocam_move_resize_cb, ph);
+
+   evas_object_smart_callback_add(ph, "clicked", my_ph_clicked, win);
+   evas_object_smart_callback_add(ph, "press", my_ph_press, win);
+   evas_object_smart_callback_add(ph, "longpressed", my_ph_longpressed, win);
+   evas_object_smart_callback_add(ph, "clicked,double", my_ph_clicked_double, win);
+   evas_object_smart_callback_add(ph, "load", my_ph_load, win);
+   evas_object_smart_callback_add(ph, "loaded", my_ph_loaded, win);
+   evas_object_smart_callback_add(ph, "load,details", my_ph_load_details, win);
+   evas_object_smart_callback_add(ph, "loaded,details", my_ph_loaded_details, win);
+   evas_object_smart_callback_add(ph, "zoom,start", my_ph_zoom_start, win);
+   evas_object_smart_callback_add(ph, "zoom,stop", my_ph_zoom_stop, win);
+   evas_object_smart_callback_add(ph, "zoom,change", my_ph_zoom_change, win);
+   evas_object_smart_callback_add(ph, "scroll,anim,start", my_ph_anim_start, win);
+   evas_object_smart_callback_add(ph, "scroll,anim,stop", my_ph_anim_stop, win);
+   evas_object_smart_callback_add(ph, "scroll,drag,start", my_ph_drag_start, win);
+   evas_object_smart_callback_add(ph, "scroll,drag,stop", my_ph_drag_stop, win);
+   evas_object_smart_callback_add(ph, "scroll", my_ph_scroll, win);
+
+   elm_photocam_file_set(ph, img[1]);
+
+   evas_object_show(ph);
+
+   tb2 = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, tb2);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Z -");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_out, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.1, 0.1);
+   elm_table_pack(tb2, bt, 0, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_fileselector_button_add(win);
+   elm_fileselector_button_label_set(bt, "Select Photo");
+   evas_object_smart_callback_add(bt, "file,chosen", my_bt_open, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.5, 0.1);
+   elm_table_pack(tb2, bt, 1, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Z +");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_in, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.1);
+   elm_table_pack(tb2, bt, 2, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Show 30,50 500x300");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_show_reg, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.1, 0.5);
+   elm_table_pack(tb2, bt, 0, 1, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Bring 800,300 500x300");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_bring_reg, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.5);
+   elm_table_pack(tb2, bt, 2, 1, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Pause On/Off");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_pause, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.1, 0.9);
+   elm_table_pack(tb2, bt, 0, 2, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Fit");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_fit, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.5, 0.9);
+   elm_table_pack(tb2, bt, 1, 2, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Fill");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_fill, ph);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.9);
+   elm_table_pack(tb2, bt, 2, 2, 1, 1);
+   evas_object_show(bt);
+
+   evas_object_show(tb2);
+
+   evas_object_resize(win, 800, 800);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_progressbar.c b/src/bin/test_progressbar.c
new file mode 100644 (file)
index 0000000..198b63c
--- /dev/null
@@ -0,0 +1,205 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+typedef struct Progressbar
+{
+   Evas_Object *pb1;
+   Evas_Object *pb2;
+   Evas_Object *pb3;
+   Evas_Object *pb4;
+   Evas_Object *pb5;
+   Evas_Object *pb6;
+   Evas_Object *pb7;
+   Eina_Bool run;
+   Ecore_Timer *timer;
+} Progressbar;
+
+static Progressbar _test_progressbar;
+
+static Eina_Bool
+_my_progressbar_value_set (void *data __UNUSED__)
+{
+   double progress;
+
+   progress = elm_progressbar_value_get (_test_progressbar.pb1);
+   if (progress < 1.0) progress += 0.0123;
+   else progress = 0.0;
+   elm_progressbar_value_set(_test_progressbar.pb1, progress);
+   elm_progressbar_value_set(_test_progressbar.pb4, progress);
+   elm_progressbar_value_set(_test_progressbar.pb3, progress);
+   elm_progressbar_value_set(_test_progressbar.pb6, progress);
+   if (progress < 1.0) return ECORE_CALLBACK_RENEW;
+   _test_progressbar.run = 0;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+my_progressbar_test_start(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_progressbar_pulse(_test_progressbar.pb2, EINA_TRUE);
+   elm_progressbar_pulse(_test_progressbar.pb5, EINA_TRUE);
+   elm_progressbar_pulse(_test_progressbar.pb7, EINA_TRUE);
+   if (!_test_progressbar.run)
+     {
+        _test_progressbar.timer = ecore_timer_add(0.1, _my_progressbar_value_set, NULL);
+        _test_progressbar.run = EINA_TRUE;
+     }
+}
+
+static void
+my_progressbar_test_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_progressbar_pulse(_test_progressbar.pb2, EINA_FALSE);
+   elm_progressbar_pulse(_test_progressbar.pb5, EINA_FALSE);
+   elm_progressbar_pulse(_test_progressbar.pb7, EINA_FALSE);
+   if (_test_progressbar.run)
+     {
+        ecore_timer_del(_test_progressbar.timer);
+        _test_progressbar.run = EINA_FALSE;
+     }
+}
+
+static void
+my_progressbar_destroy(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   my_progressbar_test_stop(NULL, NULL, NULL);
+   evas_object_del(obj);
+}
+
+void
+test_progressbar(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *pb, *bx, *hbx, *bt, *bt_bx, *ic1, *ic2;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "progressbar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Progressbar");
+   evas_object_smart_callback_add(win, "delete,request", 
+                                  my_progressbar_destroy, NULL);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   pb = elm_progressbar_add(win);
+   evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
+   elm_box_pack_end(bx, pb);
+//   elm_progressbar_horizontal_set(pb, EINA_TRUE);
+//   elm_progressbar_label_set(pb, "Progression %");
+//   elm_progressbar_unit_format_set(pb, NULL);
+   evas_object_show(pb);
+   _test_progressbar.pb1 = pb;
+
+   pb = elm_progressbar_add(win);
+   evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_progressbar_label_set(pb, "Infinite bounce");
+   elm_progressbar_pulse_set(pb, EINA_TRUE);
+   elm_box_pack_end(bx, pb);
+   evas_object_show(pb);
+   _test_progressbar.pb2 = pb;
+
+   ic1 = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic1, buf, NULL);
+   evas_object_size_hint_aspect_set(ic1, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   pb = elm_progressbar_add(win);
+   elm_progressbar_label_set(pb, "Label");
+   elm_progressbar_icon_set(pb, ic1);
+   elm_progressbar_inverted_set(pb, 1);
+   elm_progressbar_unit_format_set(pb, "%1.1f units");
+   elm_progressbar_span_size_set(pb, 200);
+   evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, pb);
+   evas_object_show(ic1);
+   evas_object_show(pb);
+   _test_progressbar.pb3 = pb;
+
+   hbx = elm_box_add(win);
+   elm_box_horizontal_set(hbx, EINA_TRUE);
+   evas_object_size_hint_weight_set(hbx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(hbx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, hbx);
+   evas_object_show(hbx);
+
+   pb = elm_progressbar_add(win);
+   elm_progressbar_horizontal_set(pb, EINA_FALSE);
+   evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(hbx, pb);
+   elm_progressbar_span_size_set(pb, 60);
+   elm_progressbar_label_set(pb, "percent");
+   evas_object_show(pb);
+   _test_progressbar.pb4 = pb;
+
+   pb = elm_progressbar_add(win);
+   elm_progressbar_horizontal_set(pb, EINA_FALSE);
+   evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_progressbar_span_size_set(pb, 80);
+   elm_progressbar_pulse_set(pb, EINA_TRUE);
+   elm_progressbar_unit_format_set(pb, NULL);
+   elm_progressbar_label_set(pb, "Infinite bounce");
+   elm_box_pack_end(hbx, pb);
+   evas_object_show(pb);
+   _test_progressbar.pb5 = pb;
+
+   ic2 = elm_icon_add(win);
+   elm_icon_file_set(ic2, buf, NULL);
+   evas_object_size_hint_aspect_set(ic2, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1);
+
+   pb = elm_progressbar_add(win);
+   elm_progressbar_horizontal_set(pb, EINA_FALSE);
+   elm_progressbar_label_set(pb, "Label");
+   elm_progressbar_icon_set(pb, ic2);
+   elm_progressbar_inverted_set(pb, 1);
+   elm_progressbar_unit_format_set(pb, "%1.2f%%");
+   elm_progressbar_span_size_set(pb, 200);
+   evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(hbx, pb);
+   evas_object_show(ic2);
+   evas_object_show(pb);
+   _test_progressbar.pb6 = pb;
+
+   pb = elm_progressbar_add(win);
+   elm_object_style_set(pb, "wheel");
+   elm_progressbar_label_set(pb, "Style: wheel");
+   evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, pb);
+   evas_object_show(pb);
+   _test_progressbar.pb7 = pb;
+
+   bt_bx = elm_box_add(win);
+   elm_box_horizontal_set(bt_bx, 1);
+   evas_object_size_hint_weight_set(bt_bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, bt_bx);
+   evas_object_show(bt_bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Start");
+   evas_object_smart_callback_add(bt, "clicked", my_progressbar_test_start, NULL);
+   elm_box_pack_end(bt_bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Stop");
+   evas_object_smart_callback_add(bt, "clicked", my_progressbar_test_stop, NULL);
+   elm_box_pack_end(bt_bx, bt);
+   evas_object_show(bt);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_radio.c b/src/bin/test_radio.c
new file mode 100644 (file)
index 0000000..6ee75ac
--- /dev/null
@@ -0,0 +1,102 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_radio(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ic, *rd, *rdg;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "radio", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Radios");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 0);
+   evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(rd, EVAS_HINT_FILL, 0.5);
+   elm_radio_label_set(rd, "Icon sized to radio");
+   elm_radio_icon_set(rd, ic);
+   elm_box_pack_end(bx, rd);
+   evas_object_show(rd);
+   evas_object_show(ic);
+   rdg = rd;
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 1);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_label_set(rd, "Icon no scale");
+   elm_radio_icon_set(rd, ic);
+   elm_box_pack_end(bx, rd);
+   evas_object_show(rd);
+   evas_object_show(ic);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 2);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_label_set(rd, "Label Only");
+   elm_box_pack_end(bx, rd);
+   evas_object_show(rd);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 3);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_label_set(rd, "Disabled");
+   elm_object_disabled_set(rd, 1);
+   elm_box_pack_end(bx, rd);
+   evas_object_show(rd);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 4);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_icon_set(rd, ic);
+   elm_box_pack_end(bx, rd);
+   evas_object_show(rd);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+
+   rd = elm_radio_add(win);
+   elm_radio_state_value_set(rd, 5);
+   elm_radio_group_add(rd, rdg);
+   elm_radio_icon_set(rd, ic);
+   elm_object_disabled_set(rd, 1);
+   elm_box_pack_end(bx, rd);
+   evas_object_show(rd);
+   evas_object_show(ic);
+
+   elm_radio_value_set(rdg, 2);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_scaling.c b/src/bin/test_scaling.c
new file mode 100644 (file)
index 0000000..aa396a7
--- /dev/null
@@ -0,0 +1,126 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_scaling(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt;
+
+   win = elm_win_add(NULL, "scaling", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Scaling");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Scale: 0.5");
+   elm_object_scale_set(bt, 0.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Scale: 0.75");
+   elm_object_scale_set(bt, 0.75);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Scale: 1.0");
+   elm_object_scale_set(bt, 1.0);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Scale: 1.5");
+   elm_object_scale_set(bt, 1.5);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Scale: 2.0");
+   elm_object_scale_set(bt, 2.0);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Scale: 3.0");
+   elm_object_scale_set(bt, 3.0);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+void
+test_scaling2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *fr, *lb;
+
+   win = elm_win_add(NULL, "scaling-2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Scaling 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   fr = elm_frame_add(win);
+   elm_object_scale_set(fr, 0.5);
+   elm_frame_label_set(fr, "Scale: 0.5");
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "Parent frame scale<br>"
+                      "is 0.5. Child should<br>"
+                      "inherit it.");
+   elm_frame_content_set(fr, lb);
+   evas_object_show(lb);
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Scale: 1.0");
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "Parent frame scale<br>"
+                      "is 1.0. Child should<br>"
+                      "inherit it.");
+   elm_frame_content_set(fr, lb);
+   evas_object_show(lb);
+   elm_object_scale_set(fr, 1.0);
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   fr = elm_frame_add(win);
+   elm_frame_label_set(fr, "Scale: 2.0");
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                      "Parent frame scale<br>"
+                      "is 2.0. Child should<br>"
+                      "inherit it.");
+   elm_frame_content_set(fr, lb);
+   evas_object_show(lb);
+   elm_object_scale_set(fr, 2.0);
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_scroller.c b/src/bin/test_scroller.c
new file mode 100644 (file)
index 0000000..7ad1d19
--- /dev/null
@@ -0,0 +1,266 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+my_bt_go_300_300(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_scroller_region_bring_in((Evas_Object *)data, 300, 300, 318, 318);
+}
+
+void
+my_bt_go_900_300(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_scroller_region_bring_in((Evas_Object *)data, 900, 300, 318, 318);
+}
+
+void
+my_bt_go_300_900(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_scroller_region_bring_in((Evas_Object *)data, 300, 900, 318, 318);
+}
+
+void
+my_bt_go_900_900(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_scroller_region_bring_in((Evas_Object *)data, 900, 900, 318, 318);
+}
+
+void
+test_scroller(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg2, *tb, *tb2, *bg, *sc, *bt;
+   int i, j, n;
+   char buf[PATH_MAX];
+   const char *img[9] =
+     {
+        "panel_01.jpg", 
+          "plant_01.jpg", 
+          "rock_01.jpg", 
+          "rock_02.jpg",
+          "sky_01.jpg", 
+          "sky_02.jpg", 
+          "sky_03.jpg", 
+          "sky_04.jpg",
+          "wood_01.jpg"
+     };
+
+   win = elm_win_add(NULL, "scroller", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Scroller");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   tb = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   n = 0;
+   for (j = 0; j < 12; j++)
+     {
+        for (i = 0; i < 12; i++)
+          {
+             bg2 = elm_bg_add(win);
+             snprintf(buf, sizeof(buf), "%s/images/%s", 
+                      PACKAGE_DATA_DIR, img[n]);
+             n++;
+             if (n >= 9) n = 0;
+             elm_bg_file_set(bg2, buf, NULL);
+             evas_object_size_hint_weight_set(bg2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             evas_object_size_hint_align_set(bg2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+             evas_object_size_hint_min_set(bg2, 318, 318);
+             elm_table_pack(tb, bg2, i, j, 1, 1);
+             evas_object_show(bg2);
+          }
+     }
+   
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, sc);
+
+   elm_scroller_content_set(sc, tb);
+   evas_object_show(tb);
+
+   elm_scroller_page_relative_set(sc, 1.0, 1.0);
+//   elm_scroller_page_size_set(sc, 200, 200);
+   evas_object_show(sc);
+
+   tb2 = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, tb2);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "to 300 300");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_go_300_300, sc);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.1, 0.1);
+   elm_table_pack(tb2, bt, 0, 0, 1, 1);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "to 900 300");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_go_900_300, sc);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.1);
+   elm_table_pack(tb2, bt, 1, 0, 1, 1);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "to 300 900");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_go_300_900, sc);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.1, 0.9);
+   elm_table_pack(tb2, bt, 0, 1, 1, 1);
+   evas_object_show(bt);
+   
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "to 900 900");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_go_900_900, sc);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, 0.9, 0.9);
+   elm_table_pack(tb2, bt, 1, 1, 1, 1);
+   evas_object_show(bt);
+   
+   evas_object_show(tb2);
+   
+   evas_object_resize(win, 320, 320);
+   evas_object_show(win);
+}
+
+void
+click_through(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   printf("click went through on %p\n", obj);
+}
+
+void
+test_scroller2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bt, *bx, *bx2, *bg, *sc, *tb, *tb2, *rc;
+   int i, j;
+
+   win = elm_win_add(NULL, "scroller2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Scroller 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0);
+
+   /* { */
+   for (i = 0; i < 3; i++)
+     {
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Vertical");
+        evas_object_smart_callback_add(bt, "clicked", click_through, NULL);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+        evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, 0.5);
+        elm_box_pack_end(bx, bt);
+        evas_object_show(bt);
+     }
+   /* } */
+   
+   /* { */
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, 0.5);
+   elm_scroller_bounce_set(sc, 1, 0);
+   elm_scroller_content_min_limit(sc, 0, 1);
+   elm_box_pack_end(bx, sc);
+   evas_object_show(sc);
+   
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+
+   for (i = 0; i < 10; i++)
+     {
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "... Horizontal scrolling ...");
+        evas_object_smart_callback_add(bt, "clicked", click_through, NULL);
+        elm_box_pack_end(bx2, bt);
+        evas_object_show(bt);
+     }
+   
+   elm_scroller_content_set(sc, bx2);
+   evas_object_show(bx2);
+   /* } */
+
+   /* { */
+   for (i = 0; i < 3; i++)
+     {
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Vertical");
+        evas_object_smart_callback_add(bt, "clicked", click_through, NULL);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+        evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, 0.5);
+        elm_box_pack_end(bx, bt);
+        evas_object_show(bt);
+     }
+   /* } */
+   
+   /* { */
+   tb = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+   
+   rc = evas_object_rectangle_add(evas_object_evas_get(win));
+   evas_object_size_hint_min_set(rc, 200, 120);
+   elm_table_pack(tb, rc, 0, 0, 1, 1);
+   
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, sc, 0, 0, 1, 1);
+   evas_object_show(sc);
+   
+   tb2 = elm_table_add(win);
+
+   for (j = 0; j < 16; j++)
+     {
+        for (i = 0; i < 16; i++)
+          {
+             bt = elm_button_add(win);
+             elm_button_label_set(bt, "Both");
+             evas_object_smart_callback_add(bt, "clicked", click_through, NULL);
+             elm_table_pack(tb2, bt, i, j, 1, 1);
+             evas_object_show(bt);
+          }
+     }
+   
+   elm_scroller_content_set(sc, tb2);
+   evas_object_show(tb2);
+   /* } */
+   
+   for (i = 0; i < 24; i++)
+     {
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, "Vertical");
+        evas_object_smart_callback_add(bt, "clicked", click_through, NULL);
+        evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+        evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, 0.5);
+        elm_box_pack_end(bx, bt);
+        evas_object_show(bt);
+     }
+   
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_scroller_bounce_set(sc, 0, 1);
+   elm_win_resize_object_add(win, sc);
+   elm_scroller_content_set(sc, bx);
+   evas_object_show(bx);
+   evas_object_show(sc);
+   
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_separator.c b/src/bin/test_separator.c
new file mode 100644 (file)
index 0000000..4a5f0e9
--- /dev/null
@@ -0,0 +1,74 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_separator(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx0, *bx, *bt, *sp;
+
+   win = elm_win_add(NULL, "separators", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Separators");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx0 = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx0, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_horizontal_set(bx0, 1);
+   elm_win_resize_object_add(win, bx0);
+   evas_object_show(bx0);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx0, bx);
+   evas_object_show(bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Left upper corner");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1); // by default, separator is vertical, we must set it horizontal
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Left lower corner");
+   elm_object_disabled_set(bt, 1);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   sp = elm_separator_add(win); // now we need vertical separator
+   elm_box_pack_end(bx0, sp);
+   evas_object_show(sp);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx0, bx);
+   evas_object_show(bx);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Right upper corner");
+   elm_object_disabled_set(bt, 1);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   sp = elm_separator_add(win);
+   elm_separator_horizontal_set(sp, 1);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Right lower corner");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_slider.c b/src/bin/test_slider.c
new file mode 100644 (file)
index 0000000..6488cda
--- /dev/null
@@ -0,0 +1,199 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+void
+_change_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+    double val = elm_slider_value_get(obj);
+    elm_slider_value_set(data, val);
+}
+
+void
+test_slider(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *sl, *ic, *sl1, *bx2;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "slider", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Slider");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   sl = elm_slider_add(win);
+   sl1 = sl;
+   elm_slider_label_set(sl, "Horizontal");
+   elm_slider_icon_set(sl, ic);
+   elm_slider_unit_format_set(sl, "%1.1f units");
+   elm_slider_span_size_set(sl, 120);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+
+   /* horizontal disable state */
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   sl = elm_slider_add(win);
+   elm_slider_label_set(sl, "Disabled");
+   elm_slider_icon_set(sl, ic);
+   elm_slider_unit_format_set(sl, "%1.1f units");
+   elm_slider_span_size_set(sl, 120);
+   elm_slider_min_max_set(sl, 50, 150);
+   elm_slider_value_set(sl, 80);
+   elm_object_disabled_set(sl, EINA_TRUE);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   sl = elm_slider_add(win);
+   elm_slider_label_set(sl, "Horizontal inverted");
+   elm_slider_end_set(sl, ic);
+   elm_slider_span_size_set(sl, 80);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%3.0f");
+   elm_slider_min_max_set(sl, 50, 150);
+   elm_slider_value_set(sl, 80);
+   elm_slider_inverted_set(sl, EINA_TRUE);
+   evas_object_size_hint_align_set(sl, 0.5, 0.5);
+   evas_object_size_hint_weight_set(sl, 0.0, 0.0);
+   elm_box_pack_end(bx, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+
+   /* label2 disable */
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   sl = elm_slider_add(win);
+   elm_slider_label_set(sl, "Disabled inverted");
+   elm_slider_end_set(sl, ic);
+   elm_slider_span_size_set(sl, 80);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%3.0f");
+   elm_slider_min_max_set(sl, 50, 150);
+   elm_slider_value_set(sl, 80);
+   elm_slider_inverted_set(sl, EINA_TRUE);
+   elm_object_disabled_set(sl, EINA_TRUE);
+   evas_object_size_hint_align_set(sl, 0.5, 0.5);
+   evas_object_size_hint_weight_set(sl, 0.0, 0.0);
+   elm_box_pack_end(bx, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+
+   sl = elm_slider_add(win);
+   elm_slider_indicator_show_set(sl, EINA_FALSE);
+   elm_slider_label_set(sl, "Scale doubled");
+   elm_slider_unit_format_set(sl, "%3.0f units");
+   elm_slider_span_size_set(sl, 40);
+   evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%3.0f");
+   elm_slider_min_max_set(sl, 50, 150);
+   elm_slider_value_set(sl, 80);
+   elm_slider_inverted_set(sl, EINA_TRUE);
+   elm_object_scale_set(sl, 2.0);
+   elm_box_pack_end(bx, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+
+   bx2 = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_horizontal_set(bx2, EINA_TRUE);
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+  
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1);
+
+   sl = elm_slider_add(win);
+   elm_slider_icon_set(sl, ic);
+   elm_slider_label_set(sl, "Vertical inverted");
+   elm_slider_inverted_set(sl, EINA_TRUE);
+   elm_slider_unit_format_set(sl, "units");
+   elm_slider_span_size_set(sl, 60);
+   evas_object_size_hint_align_set(sl, 0.5, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(sl, 0.0, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_value_set(sl, 0.2);
+   elm_object_scale_set(sl, 1.0);
+   elm_slider_horizontal_set(sl, 0);
+   elm_box_pack_end(bx2, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+
+   evas_object_smart_callback_add(sl1, "changed", _change_cb, sl);
+
+   sl = elm_slider_add(win);
+   elm_slider_label_set(sl, "Vertical");
+   elm_slider_unit_format_set(sl, "units");
+   elm_slider_span_size_set(sl, 60);
+   evas_object_size_hint_align_set(sl, 0.5, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(sl, 0.0, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_value_set(sl, 0.2);
+   elm_object_scale_set(sl, 1.0);
+   elm_slider_horizontal_set(sl, EINA_FALSE);
+   elm_box_pack_end(bx2, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+
+   /* vertical disable state */
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1);
+
+   sl = elm_slider_add(win);
+   elm_slider_icon_set(sl, ic);
+   elm_slider_label_set(sl, "Disabled vertical");
+   elm_slider_inverted_set(sl, EINA_TRUE);
+   elm_slider_unit_format_set(sl, "units");
+   elm_slider_span_size_set(sl, 100);
+   evas_object_size_hint_align_set(sl, 0.5, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(sl, 0.0, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%1.1f");
+   elm_slider_value_set(sl, 0.2);
+   elm_object_scale_set(sl, 1.0);
+   elm_slider_horizontal_set(sl, 0);
+   elm_object_disabled_set(sl, EINA_TRUE);
+   elm_box_pack_end(bx2, sl);
+   evas_object_show(ic);
+   evas_object_show(sl);
+    
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_slideshow.c b/src/bin/test_slideshow.c
new file mode 100644 (file)
index 0000000..f337bfc
--- /dev/null
@@ -0,0 +1,215 @@
+#include <Elementary.h>
+#include <elementary_config.h>
+#ifndef ELM_LIB_QUICKLAUNCH
+
+static Evas_Object *slideshow, *bt_start, *bt_stop;
+static Elm_Slideshow_Item_Class itc;
+static const char *img1 = PACKAGE_DATA_DIR"/images/logo.png";
+static const char *img2 = PACKAGE_DATA_DIR"/images/plant_01.jpg";
+static const char *img3 = PACKAGE_DATA_DIR"/images/rock_01.jpg";
+static const char *img4 = PACKAGE_DATA_DIR"/images/rock_02.jpg";
+static const char *img5 = PACKAGE_DATA_DIR"/images/sky_01.jpg";
+static const char *img6 = PACKAGE_DATA_DIR"/images/sky_04.jpg";
+static const char *img7 = PACKAGE_DATA_DIR"/images/wood_01.jpg";
+static const char *img8 = PACKAGE_DATA_DIR"/images/mystrale.jpg";
+static const char *img9 = PACKAGE_DATA_DIR"/images/mystrale_2.jpg";
+
+static void
+_notify_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_show(data);
+}
+
+static void
+_next(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_slideshow_next(data);
+}
+
+static void
+_previous(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_slideshow_previous(data);
+}
+
+static void
+_mouse_in(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_notify_timeout_set(data, 0.0);
+   evas_object_show(data);
+}
+
+
+static void
+_mouse_out(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_notify_timeout_set(data, 3.0);
+}
+
+static void
+_hv_select(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   elm_slideshow_transition_set(slideshow, data);
+   elm_hoversel_label_set(obj, data);
+}
+
+static void
+_layout_select(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   elm_slideshow_layout_set(slideshow, data);
+   elm_hoversel_label_set(obj, data);
+}
+
+static void
+_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_slideshow_timeout_set(slideshow, elm_spinner_value_get(data));
+
+   elm_object_disabled_set(bt_start, EINA_TRUE);
+   elm_object_disabled_set(bt_stop, EINA_FALSE);
+}
+
+static void
+_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_slideshow_timeout_set(slideshow, 0.0);
+   elm_object_disabled_set(bt_start, EINA_FALSE);
+   elm_object_disabled_set(bt_stop, EINA_TRUE);
+}
+
+static void
+_spin(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   if (elm_slideshow_timeout_get(slideshow) > 0)
+     elm_slideshow_timeout_set(slideshow, elm_spinner_value_get(data));
+}
+
+static Evas_Object *
+_get(void *data, Evas_Object *obj)
+{
+   //Evas_Object *photo = elm_photocam_add(obj);
+   //elm_photocam_file_set(photo, data);
+   //elm_photocam_zoom_mode_set(photo, ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT);
+
+   Evas_Object *photo = elm_photo_add(obj);
+   elm_photo_file_set(photo, data);
+   elm_photo_fill_inside_set(photo, EINA_TRUE);
+   elm_object_style_set(photo, "shadow");
+
+   return photo;
+}
+
+
+
+void
+test_slideshow(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *notify, *bx, *bt, *hv, *spin;
+   const Eina_List *l;
+   const char *transition, *layout;
+
+   win = elm_win_add(NULL, "Slideshow", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Slideshow");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   slideshow = elm_slideshow_add(win);
+   elm_slideshow_loop_set(slideshow, EINA_TRUE);
+   elm_win_resize_object_add(win, slideshow);
+   evas_object_size_hint_weight_set(slideshow, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(slideshow);
+
+   itc.func.get = _get;
+   itc.func.del = NULL;
+
+   elm_slideshow_item_add(slideshow, &itc, img1);
+   elm_slideshow_item_add(slideshow, &itc, img2);
+   elm_slideshow_item_add(slideshow, &itc, img3);
+   elm_slideshow_item_add(slideshow, &itc, img4);
+   elm_slideshow_item_add(slideshow, &itc, img9);
+   elm_slideshow_item_add(slideshow, &itc, img5);
+   elm_slideshow_item_add(slideshow, &itc, img6);
+   elm_slideshow_item_add(slideshow, &itc, img7);
+   elm_slideshow_item_add(slideshow, &itc, img8);
+
+   notify = elm_notify_add(win);
+   elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM);
+   elm_win_resize_object_add(win, notify);
+   elm_notify_timeout_set(notify, 3.0);
+
+   bx = elm_box_add(win);
+   elm_box_horizontal_set(bx, EINA_TRUE);
+   elm_notify_content_set(notify, bx);
+   evas_object_show(bx);
+
+   evas_object_event_callback_add(bx, EVAS_CALLBACK_MOUSE_IN, _mouse_in,
+                                  notify);
+   evas_object_event_callback_add(bx, EVAS_CALLBACK_MOUSE_OUT, _mouse_out,
+                                  notify);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Previous");
+   evas_object_smart_callback_add(bt, "clicked", _previous, slideshow);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Next");
+   evas_object_smart_callback_add(bt, "clicked", _next, slideshow);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   hv = elm_hoversel_add(win);
+   elm_box_pack_end(bx, hv);
+   elm_hoversel_hover_parent_set(hv, win);
+   EINA_LIST_FOREACH(elm_slideshow_transitions_get(slideshow), l, transition)
+      elm_hoversel_item_add(hv, transition, NULL, 0, _hv_select, transition);
+   elm_hoversel_label_set(hv, eina_list_data_get(elm_slideshow_transitions_get(slideshow)));
+   evas_object_show(hv);
+
+   hv = elm_hoversel_add(win);
+   elm_box_pack_end(bx, hv);
+   elm_hoversel_hover_parent_set(hv, win);
+   EINA_LIST_FOREACH(elm_slideshow_layouts_get(slideshow), l, layout)
+       elm_hoversel_item_add(hv, layout,  NULL, 0, _layout_select, layout);
+   elm_hoversel_label_set(hv, elm_slideshow_layout_get(slideshow));
+   evas_object_show(hv);
+
+   spin = elm_spinner_add(win);
+   elm_spinner_label_format_set(spin, "%2.0f secs.");
+   evas_object_smart_callback_add(spin, "changed", _spin, spin);
+   elm_spinner_step_set(spin, 1);
+   elm_spinner_min_max_set(spin, 1, 30);
+   elm_spinner_value_set(spin, 3);
+   elm_box_pack_end(bx, spin);
+   evas_object_show(spin);
+
+   bt = elm_button_add(win);
+   bt_start = bt;
+   elm_button_label_set(bt, "Start");
+   evas_object_smart_callback_add(bt, "clicked", _start, spin);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   bt_stop = bt;
+   elm_button_label_set(bt, "Stop");
+   evas_object_smart_callback_add(bt, "clicked", _stop, spin);
+   elm_box_pack_end(bx, bt);
+   elm_object_disabled_set(bt, EINA_TRUE);
+   evas_object_show(bt);
+
+   evas_object_event_callback_add(slideshow, EVAS_CALLBACK_MOUSE_UP,
+                                  _notify_show, notify);
+   evas_object_event_callback_add(slideshow, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _notify_show, notify);
+
+   evas_object_resize(win, 500, 400);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_spinner.c b/src/bin/test_spinner.c
new file mode 100644 (file)
index 0000000..39027ed
--- /dev/null
@@ -0,0 +1,89 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_spinner(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *sp;
+
+   win = elm_win_add(NULL, "spinner", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Spinner");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   sp = elm_spinner_add(win);
+   elm_spinner_label_format_set(sp, "%1.1f units");
+   elm_spinner_step_set(sp, 1.3);
+   elm_spinner_wrap_set(sp, 1);
+   elm_spinner_min_max_set(sp, -50.0, 250.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   sp = elm_spinner_add(win);
+   elm_spinner_label_format_set(sp, "Percentage %%%1.2f something");
+   elm_spinner_step_set(sp, 5.0);
+   elm_spinner_wrap_set(sp, 1);
+   elm_spinner_min_max_set(sp, 0.0, 100.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   sp = elm_spinner_add(win);
+   elm_spinner_label_format_set(sp, "%1.1f units");
+   elm_spinner_step_set(sp, 1.3);
+   elm_spinner_wrap_set(sp, 1);
+   elm_object_style_set (sp, "vertical");
+   elm_spinner_min_max_set(sp, -50.0, 250.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   sp = elm_spinner_add(win);
+   elm_spinner_label_format_set(sp, "Disabled %.0f");
+   elm_object_disabled_set(sp, 1);
+   elm_spinner_min_max_set(sp, -50.0, 250.0);
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   sp = elm_spinner_add(win);
+   elm_spinner_min_max_set(sp, 1, 12);
+   elm_spinner_label_format_set(sp, "%.0f");
+   elm_spinner_step_set(sp, 1.0);
+   elm_spinner_editable_set(sp, EINA_FALSE);
+   elm_spinner_special_value_add(sp, 1, "January");
+   elm_spinner_special_value_add(sp, 2, "February");
+   elm_spinner_special_value_add(sp, 3, "March");
+   elm_spinner_special_value_add(sp, 4, "April");
+   elm_spinner_special_value_add(sp, 5, "May");
+   elm_spinner_special_value_add(sp, 6, "June");
+   elm_spinner_special_value_add(sp, 7, "July");
+   elm_spinner_special_value_add(sp, 8, "August");
+   elm_spinner_special_value_add(sp, 9, "September");
+   elm_spinner_special_value_add(sp, 10, "October");
+   elm_spinner_special_value_add(sp, 11, "November");
+   elm_spinner_special_value_add(sp, 12, "December");
+   evas_object_size_hint_align_set(sp, EVAS_HINT_FILL, 0.5);
+   evas_object_size_hint_weight_set(sp, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, sp);
+   evas_object_show(sp);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_store.c b/src/bin/test_store.c
new file mode 100644 (file)
index 0000000..64ce49d
--- /dev/null
@@ -0,0 +1,268 @@
+#include <Elementary.h>
+
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct _My_Item My_Item;
+
+struct _My_Item
+{
+  char *from, *subject, *date, *head_content;
+};
+
+// callbacks just to see user interacting with genlist
+static void
+_st_selected(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("selected: %p\n", event_info);
+}
+
+static void
+_st_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("clicked: %p\n", event_info);
+}
+
+static void
+_st_longpress(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   printf("longpress %p\n", event_info);
+}
+
+// store callbacks to handle loading/parsing/freeing of store items from src
+static Elm_Genlist_Item_Class itc1 =
+{
+  "message", { NULL, NULL, NULL, NULL }
+};
+
+static const Elm_Store_Item_Mapping it1_mapping[] =
+{
+  {
+    ELM_STORE_ITEM_MAPPING_LABEL,
+      "elm.title.1", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, from),
+      { .empty = {
+        EINA_TRUE
+      } } },
+  {
+    ELM_STORE_ITEM_MAPPING_LABEL,
+      "elm.title.2", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, subject),
+      { .empty = {
+        EINA_TRUE
+      } } },
+  {
+    ELM_STORE_ITEM_MAPPING_LABEL,
+      "elm.text", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, head_content),
+      { .empty = {
+        EINA_TRUE
+      } } },
+  {
+    ELM_STORE_ITEM_MAPPING_ICON,
+      "elm.swallow.icon", 0,
+      { .icon = {
+        48, 48, 
+        ELM_ICON_LOOKUP_THEME_FDO,
+        EINA_TRUE, EINA_FALSE,
+        EINA_TRUE,
+        EINA_FALSE, EINA_FALSE,
+      } } },
+  {
+    ELM_STORE_ITEM_MAPPING_CUSTOM,
+      "elm.swallow.end", 0,
+      { .custom = {
+        NULL
+      } } },
+  ELM_STORE_ITEM_MAPPING_END
+};
+
+
+////// **** WARNING ***********************************************************
+////   * This function runs inside a thread outside efl mainloop. Be careful! *
+//     ************************************************************************
+static Eina_Bool
+_st_store_list(void *data __UNUSED__, Elm_Store_Item_Info *item_info)
+{
+  Elm_Store_Item_Info_Filesystem *info = (Elm_Store_Item_Info_Filesystem *)item_info;
+  int id;
+  char sort_id[7];
+
+  // create a sort id based on the filename itself assuming it is a numeric
+  // value like the id number in mh mail folders which is what this test
+  // uses as a data source
+  char *file = strrchr(info->path, '/');
+  if (file) file++;
+  else file = info->path;
+  id = atoi(file);
+  sort_id[0] = ((id >> 30) & 0x3f) + 32;
+  sort_id[1] = ((id >> 24) & 0x3f) + 32;
+  sort_id[2] = ((id >> 18) & 0x3f) + 32;
+  sort_id[3] = ((id >> 12) & 0x3f) + 32;
+  sort_id[4] = ((id >>  6) & 0x3f) + 32;
+  sort_id[5] = ((id >>  0) & 0x3f) + 32;
+  sort_id[6] = 0;
+  info->base.sort_id = strdup(sort_id);
+  // choose the item genlist item class to use (only item style should be
+  // provided by the app, store will fill everything else in, so it also
+  // has to be writable
+  info->base.item_class = &itc1; // based on item info - return the item class wanted (only style field used - rest reset to internal funcs store sets up to get label/icon etc)
+  info->base.mapping = it1_mapping;
+  info->base.data = NULL; // if we can already parse and load all of item here and want to - set this
+  return EINA_TRUE; // return true to include this, false not to
+}
+//     ************************************************************************
+////   * End of separate thread function.                                     *
+////// ************************************************************************
+
+////// **** WARNING ***********************************************************
+////   * This function runs inside a thread outside efl mainloop. Be careful! *
+//     ************************************************************************
+static void
+_st_store_fetch(void *data __UNUSED__, Elm_Store_Item *sti)
+{
+  const char *path = elm_store_item_filesystem_path_get(sti);
+  My_Item *myit;
+  FILE *f;
+  char buf[4096], *p;
+  Eina_Bool have_content = EINA_FALSE;
+  char *content = NULL, *content_pos = NULL, *content_end = NULL;
+
+  // if we already have my item data - skip
+  if (elm_store_item_data_get(sti)) return;
+  // open the mail file and parse it
+  f = fopen(path, "r");
+  if (!f) return;
+  
+  // alloc my item in memory that holds data to show in the list
+  myit = calloc(1, sizeof(My_Item));
+  if (!myit)
+    {
+      fclose(f);
+      return;
+    }
+  while (fgets(buf, sizeof(buf), f))
+    {
+      if (!have_content)
+        {
+          if (!isblank(buf[0]))
+            {
+              // get key: From:, Subject: etc.
+              if (!strncmp(buf, "From:", 5))
+                {
+                  p = buf + 5;
+                  while ((*p) && (isblank(*p))) p++;
+                  p = strdup(p);
+                  if (p)
+                    {
+                      myit->from = p;
+                      p = strchr(p, '\n');
+                      if (p) *p = 0;
+                    }
+                }
+              else if (!strncmp(buf, "Subject:", 8))
+                {
+                  p = buf + 8;
+                  while ((*p) && (isblank(*p))) p++;
+                  p = strdup(p);
+                  if (p)
+                    {
+                      myit->subject = p;
+                      p = strchr(p, '\n');
+                      if (p) *p = 0;
+                    }
+                }
+              else if (!strncmp(buf, "Date:", 5))
+                {
+                  p = buf + 5;
+                  while ((*p) && (isblank(*p))) p++;
+                  p = strdup(p);
+                  if (p)
+                    {
+                      myit->date = p;
+                      p = strchr(p, '\n');
+                      if (p) *p = 0;
+                    }
+                }
+              else if (buf[0] == '\n') // begin of content
+                have_content = EINA_TRUE;
+            }
+        }
+      else
+        {
+          // get first 320 bytes of content/body
+          if (!content)
+            {
+              content = calloc(1, 320);
+              content_pos = content;
+              content_end = content + 319;
+            }
+          strncat(content_pos, buf, content_end - content_pos - 1);
+          content_pos = content + strlen(content);
+        }
+    }
+  fclose(f);
+  myit->head_content = elm_entry_utf8_to_markup(content);
+  free(content);
+  elm_store_item_data_set(sti, myit);
+}
+//     ************************************************************************
+////   * End of separate thread function.                                     *
+////// ************************************************************************
+
+static void
+_st_store_unfetch(void *data __UNUSED__, Elm_Store_Item *sti)
+{
+  My_Item *myit = elm_store_item_data_get(sti);
+  if (!myit) return;
+  if (myit->from) free(myit->from);
+  if (myit->subject) free(myit->subject);
+  if (myit->date) free(myit->date);
+  if (myit->head_content) free(myit->head_content);
+  free(myit);
+  elm_store_item_data_set(sti, NULL);
+}
+
+void
+test_store(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+  Evas_Object *win, *bg, *gl, *bx;
+  
+  Elm_Store *st;
+
+  win = elm_win_add(NULL, "store", ELM_WIN_BASIC);
+  elm_win_title_set(win, "Store");
+  elm_win_autodel_set(win, 1);
+  
+  bg = elm_bg_add(win);
+  elm_win_resize_object_add(win, bg);
+  evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+  evas_object_show(bg);
+  
+  bx = elm_box_add(win);
+  evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+  elm_win_resize_object_add(win, bx);
+  evas_object_show(bx);
+  
+  gl = elm_genlist_add(win);
+  elm_genlist_height_for_width_mode_set(gl, EINA_TRUE);
+  evas_object_smart_callback_add(gl, "selected", _st_selected, NULL);
+  evas_object_smart_callback_add(gl, "clicked", _st_clicked, NULL);
+  evas_object_smart_callback_add(gl, "longpressed", _st_longpress, NULL);
+  evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+  evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+  elm_box_pack_end(bx, gl);
+  evas_object_show(gl);
+
+  st = elm_store_filesystem_new();
+  elm_store_list_func_set(st, _st_store_list, NULL);
+  elm_store_fetch_func_set(st, _st_store_fetch, NULL);
+  //elm_store_fetch_thread_set(st, EINA_FALSE);
+  elm_store_unfetch_func_set(st, _st_store_unfetch, NULL);
+  elm_store_sorted_set(st, EINA_TRUE);
+  elm_store_target_genlist_set(st, gl);
+  elm_store_filesystem_directory_set(st, "./store");
+  
+  evas_object_resize(win, 480, 800);
+  evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_table.c b/src/bin/test_table.c
new file mode 100644 (file)
index 0000000..dd0bb99
--- /dev/null
@@ -0,0 +1,69 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_table(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *tb, *bt;
+
+   win = elm_win_add(NULL, "table", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Table");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   tb = elm_table_add(win);
+   elm_win_resize_object_add(win, tb);
+   evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(tb);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 1");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, bt, 0, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 2");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, bt, 1, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 3");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, bt, 2, 0, 1, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 4");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, bt, 0, 1, 2, 1);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 5");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, bt, 2, 1, 1, 3);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button 6");
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_table_pack(tb, bt, 0, 2, 2, 2);
+   evas_object_show(bt);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_thumb.c b/src/bin/test_thumb.c
new file mode 100644 (file)
index 0000000..b6f2f9d
--- /dev/null
@@ -0,0 +1,70 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_thumb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *sc, *tb, *th;
+   int i, j, n;
+   char buf[PATH_MAX];
+   const char *img[9] =
+     {
+       "panel_01.jpg",
+       "plant_01.jpg",
+       "rock_01.jpg",
+       "rock_02.jpg",
+       "sky_01.jpg",
+       "sky_02.jpg",
+       "sky_03.jpg",
+       "sky_04.jpg",
+       "wood_01.jpg",
+     };
+
+   elm_need_ethumb();
+
+   win = elm_win_add(NULL, "thumb", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Thumb");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   tb = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   n = 0;
+   for (j = 0; j < 12; j++)
+     {
+        for (i = 0; i < 12; i++)
+          {
+             th = elm_thumb_add(win);
+             snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR,
+                     img[n]);
+            n = (n + 1) % 9;
+             elm_thumb_file_set(th, buf, img[n]);
+             evas_object_size_hint_weight_set(th, EVAS_HINT_EXPAND,
+                                              EVAS_HINT_EXPAND);
+            evas_object_size_hint_align_set(th, EVAS_HINT_FILL,
+                                            EVAS_HINT_FILL);
+             elm_table_pack(tb, th, i, j, 1, 1);
+            elm_thumb_editable_set(th, EINA_TRUE);
+             evas_object_show(th);
+          }
+     }
+
+   sc = elm_scroller_add(win);
+   evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, sc);
+
+   elm_scroller_content_set(sc, tb);
+   evas_object_show(tb);
+   evas_object_show(sc);
+
+   evas_object_resize(win, 600, 600);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_toggle.c b/src/bin/test_toggle.c
new file mode 100644 (file)
index 0000000..e8046f1
--- /dev/null
@@ -0,0 +1,87 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+void
+test_toggle(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *ic, *tg;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "toggles", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Toggles");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   tg = elm_toggle_add(win);
+   evas_object_size_hint_weight_set(tg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(tg, EVAS_HINT_FILL, 0.5);
+   elm_toggle_label_set(tg, "Icon sized to toggle");
+   elm_toggle_icon_set(tg, ic);
+   elm_toggle_state_set(tg, 1);
+   elm_toggle_states_labels_set(tg, "Yes", "No");
+   elm_box_pack_end(bx, tg);
+   evas_object_show(tg);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+
+   tg = elm_toggle_add(win);
+   elm_toggle_label_set(tg, "Icon no scale");
+   elm_toggle_icon_set(tg, ic);
+   elm_box_pack_end(bx, tg);
+   evas_object_show(tg);
+   evas_object_show(ic);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+
+   tg = elm_toggle_add(win);
+   elm_toggle_label_set(tg, "Icon no scale");
+   elm_toggle_icon_set(tg, ic);
+   elm_object_disabled_set(tg, 1);
+   elm_box_pack_end(bx, tg);
+   evas_object_show(tg);
+   evas_object_show(ic);
+
+   tg = elm_toggle_add(win);
+   elm_toggle_label_set(tg, "Label Only");
+   elm_toggle_states_labels_set(tg, "Big long fun times label", 
+                                "Small long happy fun label");
+   elm_box_pack_end(bx, tg);
+   evas_object_show(tg);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+
+   tg = elm_toggle_add(win);
+   elm_toggle_icon_set(tg, ic);
+   elm_box_pack_end(bx, tg);
+   evas_object_show(tg);
+   evas_object_show(ic);
+
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_toolbar.c b/src/bin/test_toolbar.c
new file mode 100644 (file)
index 0000000..ca46fa4
--- /dev/null
@@ -0,0 +1,618 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+static void
+tb_1(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "%s/images/panel_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(data, buf);
+}
+
+static void
+tb_2(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "%s/images/rock_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(data, buf);
+}
+
+static void
+tb_3(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "%s/images/wood_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(data, buf);
+}
+
+static void
+tb_3a(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   tb_3(data, obj, event_info);
+   elm_toolbar_item_state_set(event_info, elm_toolbar_item_state_next(event_info));
+}
+
+static void
+tb_3b(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   tb_3(data, obj, event_info);
+   elm_toolbar_item_state_unset(event_info);
+}
+
+static void
+tb_4(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "%s/images/sky_03.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(data, buf);
+}
+
+static void
+tb_4a(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_toolbar_item_state_set(event_info, elm_toolbar_item_state_prev(event_info));
+}
+
+static void
+tb_5(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_photo_file_set(data, NULL);
+}
+
+void
+test_toolbar(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *tb, *ph, *menu;
+   Evas_Object *ph1, *ph2, *ph3, *ph4;
+   Elm_Toolbar_Item *item;
+   Elm_Menu_Item *menu_item;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "toolbar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Toolbar");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   tb = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(tb, 0);
+   elm_toolbar_mode_shrink_set(tb, ELM_TOOLBAR_SHRINK_MENU);
+   evas_object_size_hint_weight_set(tb, 0.0, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
+   
+   ph1 = elm_photo_add(win);
+   ph2 = elm_photo_add(win);
+   ph3 = elm_photo_add(win);
+   ph4 = elm_photo_add(win);
+
+   item = elm_toolbar_item_append(tb, "document-print", "Hello", tb_1, ph1);
+   elm_toolbar_item_disabled_set(item, EINA_TRUE);
+   elm_toolbar_item_priority_set(item, 100);
+
+   item = elm_toolbar_item_append(tb, "folder-new", "World", tb_2, ph1);
+   elm_toolbar_item_priority_set(item, -100);
+
+   item = elm_toolbar_item_append(tb, "object-rotate-right", "H", tb_3, ph4);
+   elm_toolbar_item_priority_set(item, 150);
+
+   item = elm_toolbar_item_append(tb, "mail-send", "Comes", tb_4, ph4);
+   elm_toolbar_item_priority_set(item, 0);
+
+   item = elm_toolbar_item_append(tb, "clock", "Elementary", tb_5, ph4);
+   elm_toolbar_item_priority_set(item, -200);
+
+   item = elm_toolbar_item_append(tb, "refresh", "Menu", NULL, NULL);
+   elm_toolbar_item_menu_set(item, 1);
+   elm_toolbar_item_priority_set(item, -999999);
+   elm_toolbar_menu_parent_set(tb, win);
+   menu = elm_toolbar_item_menu_get(item);
+   elm_menu_item_add(menu, NULL, "edit-cut", "Shrink", tb_3, ph4);
+   menu_item = elm_menu_item_add(menu, NULL, "edit-copy", "Mode", tb_4, ph4);
+   elm_menu_item_add(menu, menu_item, "edit-paste", "is set to", tb_4, ph4);
+   elm_menu_item_add(menu, NULL, "edit-delete", "Menu", tb_5, ph4);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   tb = elm_table_add(win);
+   //elm_table_homogenous_set(tb, 1);
+   evas_object_size_hint_weight_set(tb, 0.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ph = ph1;
+   elm_photo_size_set(ph, 40);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph2;
+   elm_photo_size_set(ph, 80);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph3;
+   elm_photo_size_set(ph, 20);
+   snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 1, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph4;
+   elm_photo_size_set(ph, 60);
+   snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 1, 1, 1);
+   evas_object_show(ph);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+void
+test_toolbar2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *tb, *ph, *menu;
+   Evas_Object *ph1, *ph2, *ph3, *ph4;
+   Elm_Toolbar_Item *item;
+   Elm_Menu_Item *menu_item;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "toolbar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Toolbar");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   tb = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(tb, 0);
+   elm_toolbar_mode_shrink_set(tb, ELM_TOOLBAR_SHRINK_SCROLL);
+   evas_object_size_hint_weight_set(tb, 0.0, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
+   
+   ph1 = elm_photo_add(win);
+   ph2 = elm_photo_add(win);
+   ph3 = elm_photo_add(win);
+   ph4 = elm_photo_add(win);
+
+   item = elm_toolbar_item_append(tb, "document-print", "Hello", tb_1, ph1);
+   elm_toolbar_item_disabled_set(item, EINA_TRUE);
+   elm_toolbar_item_priority_set(item, -100);
+
+   item = elm_toolbar_item_append(tb, "folder-new", "World", tb_2, ph1);
+   elm_toolbar_item_priority_set(item, 100);
+
+   item = elm_toolbar_item_append(tb, "object-rotate-right", "H", tb_3, ph4);
+   elm_toolbar_item_priority_set(item, -150);
+
+   item = elm_toolbar_item_append(tb, "mail-send", "Comes", tb_4, ph4);
+   elm_toolbar_item_priority_set(item, -200);
+
+   item = elm_toolbar_item_append(tb, "clock", "Elementary", tb_5, ph4);
+   elm_toolbar_item_priority_set(item, 0);
+
+   item = elm_toolbar_item_append(tb, "refresh", "Menu", NULL, NULL);
+   elm_toolbar_item_menu_set(item, 1);
+   elm_toolbar_item_priority_set(item, -999999);
+   elm_toolbar_menu_parent_set(tb, win);
+   menu = elm_toolbar_item_menu_get(item);
+   elm_menu_item_add(menu, NULL, "edit-cut", "Shrink", tb_3, ph4);
+   menu_item = elm_menu_item_add(menu, NULL, "edit-copy", "Mode", tb_4, ph4);
+   elm_menu_item_add(menu, menu_item, "edit-paste", "is set to", tb_4, ph4);
+   elm_menu_item_add(menu, NULL, "edit-delete", "Scroll", tb_5, ph4);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   tb = elm_table_add(win);
+   //elm_table_homogenous_set(tb, 1);
+   evas_object_size_hint_weight_set(tb, 0.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ph = ph1;
+   elm_photo_size_set(ph, 40);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph2;
+   elm_photo_size_set(ph, 80);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph3;
+   elm_photo_size_set(ph, 20);
+   snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 1, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph4;
+   elm_photo_size_set(ph, 60);
+   snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 1, 1, 1);
+   evas_object_show(ph);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+void
+test_toolbar3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *tb, *ph, *menu;
+   Evas_Object *ph1, *ph2, *ph3, *ph4;
+   Elm_Toolbar_Item *item;
+   Elm_Menu_Item *menu_item;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "toolbar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Toolbar");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   tb = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(tb, 0);
+   elm_toolbar_mode_shrink_set(tb, ELM_TOOLBAR_SHRINK_NONE);
+   evas_object_size_hint_weight_set(tb, 0.0, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
+   
+   ph1 = elm_photo_add(win);
+   ph2 = elm_photo_add(win);
+   ph3 = elm_photo_add(win);
+   ph4 = elm_photo_add(win);
+
+   item = elm_toolbar_item_append(tb, "document-print", "Hello", tb_1, ph1);
+   elm_toolbar_item_disabled_set(item, EINA_TRUE);
+   elm_toolbar_item_priority_set(item, 0);
+
+   item = elm_toolbar_item_append(tb, "folder-new", "World", tb_2, ph1);
+   elm_toolbar_item_priority_set(item, -200);
+
+   item = elm_toolbar_item_append(tb, "object-rotate-right", "H", tb_3, ph4);
+   elm_toolbar_item_priority_set(item, 1);
+
+   item = elm_toolbar_item_append(tb, "mail-send", "Comes", tb_4, ph4);
+   elm_toolbar_item_priority_set(item, -10);
+
+   item = elm_toolbar_item_append(tb, "clock", "Elementary", tb_5, ph4);
+   elm_toolbar_item_priority_set(item, 50);
+
+   item = elm_toolbar_item_append(tb, "refresh", "Menu", NULL, NULL);
+   elm_toolbar_item_menu_set(item, 1);
+   elm_toolbar_item_priority_set(item, 999999);
+   elm_toolbar_menu_parent_set(tb, win);
+   menu = elm_toolbar_item_menu_get(item);
+   elm_menu_item_add(menu, NULL, "edit-cut", "Shrink", tb_3, ph4);
+   menu_item = elm_menu_item_add(menu, NULL, "edit-copy", "Mode", tb_4, ph4);
+   elm_menu_item_add(menu, menu_item, "edit-paste", "is set to", tb_4, ph4);
+   elm_menu_item_add(menu, NULL, "edit-delete", "None", tb_5, ph4);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   tb = elm_table_add(win);
+   //elm_table_homogenous_set(tb, 1);
+   evas_object_size_hint_weight_set(tb, 0.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ph = ph1;
+   elm_photo_size_set(ph, 40);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph2;
+   elm_photo_size_set(ph, 80);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph3;
+   elm_photo_size_set(ph, 20);
+   snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 1, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph4;
+   elm_photo_size_set(ph, 60);
+   snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 1, 1, 1);
+   evas_object_show(ph);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+/* The same test of toolbar, but using hide shrink mode instead of menu */
+void
+test_toolbar4(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *tb, *ph, *menu;
+   Evas_Object *ph1, *ph2, *ph3, *ph4;
+   Elm_Toolbar_Item *item;
+   Elm_Menu_Item *menu_item;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "toolbar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Toolbar 4");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   tb = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(tb, 0);
+   elm_toolbar_mode_shrink_set(tb, ELM_TOOLBAR_SHRINK_HIDE);
+   evas_object_size_hint_weight_set(tb, 0.0, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
+
+   ph1 = elm_photo_add(win);
+   ph2 = elm_photo_add(win);
+   ph3 = elm_photo_add(win);
+   ph4 = elm_photo_add(win);
+
+   item = elm_toolbar_item_append(tb, "document-print", "Hello", tb_1, ph1);
+   elm_toolbar_item_disabled_set(item, EINA_TRUE);
+   elm_toolbar_item_priority_set(item, 100);
+
+   item = elm_toolbar_item_append(tb, "folder-new", "World", tb_2, ph1);
+   elm_toolbar_item_priority_set(item, -100);
+
+   item = elm_toolbar_item_append(tb, "object-rotate-right", "H", tb_3, ph4);
+   elm_toolbar_item_priority_set(item, 150);
+
+   item = elm_toolbar_item_append(tb, "mail-send", "Comes", tb_4, ph4);
+   elm_toolbar_item_priority_set(item, 0);
+
+   item = elm_toolbar_item_append(tb, "clock", "Elementary", tb_5, ph4);
+   elm_toolbar_item_priority_set(item, -200);
+
+   item = elm_toolbar_item_append(tb, "refresh", "Menu", NULL, NULL);
+   elm_toolbar_item_menu_set(item, 1);
+   elm_toolbar_item_priority_set(item, -999999);
+   elm_toolbar_menu_parent_set(tb, win);
+   menu = elm_toolbar_item_menu_get(item);
+
+   elm_menu_item_add(menu, NULL, "edit-cut", "Shrink", tb_3, ph4);
+   menu_item = elm_menu_item_add(menu, NULL, "edit-copy", "Mode", tb_4, ph4);
+   elm_menu_item_add(menu, menu_item, "edit-paste", "is set to", tb_4, ph4);
+   elm_menu_item_add(menu, NULL, "edit-delete", "Menu", tb_5, ph4);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   tb = elm_table_add(win);
+   evas_object_size_hint_weight_set(tb, 0.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ph = ph1;
+   elm_photo_size_set(ph, 40);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph2;
+   elm_photo_size_set(ph, 80);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph3;
+   elm_photo_size_set(ph, 20);
+   snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 1, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph4;
+   elm_photo_size_set(ph, 60);
+   snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 1, 1, 1);
+   evas_object_show(ph);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+
+/* Toolbar with multiple state buttons */
+void
+test_toolbar5(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *tb, *ph, *menu;
+   Evas_Object *ph1, *ph2, *ph3, *ph4;
+   Elm_Toolbar_Item *item;
+   Elm_Menu_Item *menu_item;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "toolbar", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Toolbar");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   tb = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(tb, 0);
+   elm_toolbar_mode_shrink_set(tb, ELM_TOOLBAR_SHRINK_MENU);
+   evas_object_size_hint_weight_set(tb, 0.0, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
+   elm_toolbar_no_select_mode_set(tb, EINA_TRUE);
+
+   ph1 = elm_photo_add(win);
+   ph2 = elm_photo_add(win);
+   ph3 = elm_photo_add(win);
+   ph4 = elm_photo_add(win);
+
+   item = elm_toolbar_item_append(tb, "document-print", "Hello", tb_1, ph1);
+   elm_toolbar_item_disabled_set(item, EINA_TRUE);
+   elm_toolbar_item_priority_set(item, 100);
+
+   item = elm_toolbar_item_append(tb, PACKAGE_DATA_DIR"/images/icon_04.png", "World", tb_2, ph1);
+   elm_toolbar_item_priority_set(item, -100);
+
+   item = elm_toolbar_item_append(tb, "object-rotate-right", "H", tb_3a, ph4);
+   elm_toolbar_item_state_add(item, "object-rotate-left", "H2", tb_3b, ph4);
+   elm_toolbar_item_priority_set(item, 150);
+
+   item = elm_toolbar_item_append(tb, "mail-send", "Comes", tb_4a, ph4);
+   elm_toolbar_item_state_add(item, "emptytrash", "Comes2", tb_4a, ph4);
+   elm_toolbar_item_state_add(item, "trashcan_full", "Comes3", tb_4a, ph4);
+   elm_toolbar_item_priority_set(item, 0);
+
+   item = elm_toolbar_item_append(tb, "clock", "Elementary", tb_5, ph4);
+   elm_toolbar_item_priority_set(item, -200);
+
+   item = elm_toolbar_item_append(tb, "refresh", "Menu", NULL, NULL);
+   elm_toolbar_item_menu_set(item, 1);
+   elm_toolbar_item_priority_set(item, -999999);
+   elm_toolbar_menu_parent_set(tb, win);
+   menu = elm_toolbar_item_menu_get(item);
+
+   elm_menu_item_add(menu, NULL, "edit-cut", "Shrink", tb_3, ph4);
+   menu_item = elm_menu_item_add(menu, NULL, "edit-copy", "Mode", tb_4, ph4);
+   elm_menu_item_add(menu, menu_item, "edit-paste", "is set to", tb_4, ph4);
+   elm_menu_item_add(menu, NULL, "edit-delete", "Menu", tb_5, ph4);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   tb = elm_table_add(win);
+   //elm_table_homogenous_set(tb, 1);
+   evas_object_size_hint_weight_set(tb, 0.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   ph = ph1;
+   elm_photo_size_set(ph, 40);
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph2;
+   elm_photo_size_set(ph, 80);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 0, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph3;
+   elm_photo_size_set(ph, 20);
+   snprintf(buf, sizeof(buf), "%s/images/sky_01.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 0, 1, 1, 1);
+   evas_object_show(ph);
+
+   ph = ph4;
+   elm_photo_size_set(ph, 60);
+   snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+   elm_photo_file_set(ph, buf);
+   evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ph, 0.5, 0.5);
+   elm_table_pack(tb, ph, 1, 1, 1, 1);
+   evas_object_show(ph);
+
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   evas_object_resize(win, 320, 300);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_tooltip.c b/src/bin/test_tooltip.c
new file mode 100644 (file)
index 0000000..1dabd1a
--- /dev/null
@@ -0,0 +1,550 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct _Testitem
+{
+   Elm_Gengrid_Item *item;
+   const char       *path;
+   int               mode;
+   int               onoff;
+} Testitem;
+
+static Elm_Gengrid_Item_Class gic;
+
+char *
+grdt_lbl_get(void            *data,
+             Evas_Object *obj __UNUSED__,
+             const char *part __UNUSED__)
+{
+   const Testitem *ti = data;
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Photo %s", ti->path);
+   return strdup(buf);
+}
+
+Evas_Object *
+grdt_icon_get(void        *data,
+              Evas_Object *obj,
+              const char  *part)
+{
+   const Testitem *ti = data;
+   if (!strcmp(part, "elm.swallow.icon"))
+     {
+        Evas_Object *icon = elm_bg_add(obj);
+        elm_bg_file_set(icon, ti->path, NULL);
+        evas_object_size_hint_aspect_set(icon,
+                                         EVAS_ASPECT_CONTROL_VERTICAL,
+                                         1, 1);
+        evas_object_show(icon);
+        return icon;
+     }
+   return NULL;
+}
+
+static Elm_Genlist_Item_Class itct;
+
+static void
+gltt_exp(void *data       __UNUSED__,
+         Evas_Object *obj __UNUSED__,
+         void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   Evas_Object *gl = elm_genlist_item_genlist_get(it);
+   int val = (int)(long)elm_genlist_item_data_get(it);
+   Elm_Genlist_Item *it1, *it2, *it3;
+
+   val *= 10;
+   it1 = elm_genlist_item_append(gl, &itct, (void *)(long)(val + 1), it,
+                                 ELM_GENLIST_ITEM_NONE, NULL, NULL);
+   it2 = elm_genlist_item_append(gl, &itct, (void *)(long)(val + 2), it,
+                                 ELM_GENLIST_ITEM_NONE, NULL, NULL);
+   it3 = elm_genlist_item_append(gl, &itct, (void *)(long)(val + 3), it,
+                                 ELM_GENLIST_ITEM_SUBITEMS, NULL, NULL);
+
+   elm_genlist_item_tooltip_text_set(it1, "Testing A");
+   elm_genlist_item_tooltip_text_set(it2, "Testing B");
+   elm_genlist_item_tooltip_text_set(it3, "Testing C");
+}
+
+static void
+gltt_con(void *data       __UNUSED__,
+         Evas_Object *obj __UNUSED__,
+         void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_subitems_clear(it);
+}
+
+static void
+gltt_exp_req(void *data       __UNUSED__,
+             Evas_Object *obj __UNUSED__,
+             void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 1);
+}
+
+static void
+gltt_con_req(void *data       __UNUSED__,
+             Evas_Object *obj __UNUSED__,
+             void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 0);
+}
+
+char *
+gltt_label_get(void            *data,
+               Evas_Object *obj __UNUSED__,
+               const char *part __UNUSED__)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item mode %i", (int)(long)data);
+   return strdup(buf);
+}
+
+static Evas_Object *
+_tt_item_icon(void *data   __UNUSED__,
+              Evas_Object *obj,
+              void *item   __UNUSED__)
+{
+   Evas_Object *ic = elm_icon_add(obj);
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png",
+            PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_resize(ic, 64, 64);
+   return ic;
+}
+
+static void
+_tt_item_icon_del(void            *data,
+                  Evas_Object *obj __UNUSED__,
+                  void            *event_info)
+{
+   // test to check for del_cb behavior!
+   printf("_tt_icon_del: data=%ld (== 456?), event_info=%p\n",
+          (long)data, event_info);
+}
+
+static void
+_tt_text_replace(void *data       __UNUSED__,
+                 Evas_Object     *obj,
+                 void *event_info __UNUSED__)
+{
+   static int count = 0;
+   char buf[64];
+   snprintf(buf, sizeof(buf), "count=%d", count);
+   count++;
+   elm_object_tooltip_text_set(obj, buf);
+}
+
+static void
+_tt_timer_del(void *data       __UNUSED__,
+              Evas *e          __UNUSED__,
+              Evas_Object     *obj,
+              void *event_info __UNUSED__)
+{
+   Ecore_Timer *timer = evas_object_data_del(obj, "test-timer");
+   if (!timer) return;
+   ecore_timer_del(timer);
+}
+
+static Eina_Bool
+_tt_text_replace_timer_cb(void *data)
+{
+   _tt_text_replace(NULL, data, NULL);
+   return EINA_TRUE;
+}
+
+static void
+_tt_text_replace_timed(void *data       __UNUSED__,
+                       Evas_Object     *obj,
+                       void *event_info __UNUSED__)
+{
+   Ecore_Timer *timer = evas_object_data_get(obj, "test-timer");
+   if (timer)
+     {
+        ecore_timer_del(timer);
+        evas_object_data_del(obj, "test-timer");
+        elm_button_label_set(obj, "Simple text tooltip, click to start"
+                                  " changed timed");
+        return;
+     }
+
+   timer = ecore_timer_add(1.5, _tt_text_replace_timer_cb, obj);
+   evas_object_data_set(obj, "test-timer", timer);
+   elm_button_label_set(obj, "Simple text tooltip, click to stop changed"
+                             " timed");
+}
+
+static Evas_Object *
+_tt_icon(void *data   __UNUSED__,
+         Evas_Object *obj)
+{
+   Evas_Object *ic = elm_icon_add(obj);
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png",
+            PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_resize(ic, 64, 64);
+   return ic;
+}
+
+static Evas_Object *
+_tt_icon2(void *data   __UNUSED__,
+          Evas_Object *obj)
+{
+   Evas_Object *ic = elm_icon_add(obj);
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "%s/images/icon_00.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   elm_icon_scale_set(ic, 0, 0);
+   evas_object_resize(ic, 64, 64);
+   return ic;
+}
+
+static void
+_tt_icon_del(void            *data,
+             Evas_Object *obj __UNUSED__,
+             void            *event_info)
+{
+   // test to check for del_cb behavior!
+   printf("_tt_icon_del: data=%ld (== 123?), event_info=%p\n",
+          (long)data, event_info);
+}
+
+static Eina_Bool
+_tt_icon_replace_timer_cb(void *data)
+{
+   static int current = 0;
+
+   elm_object_tooltip_content_cb_set
+     (data, current ? _tt_icon2 : _tt_icon, NULL, NULL);
+
+   current = !current;
+   return EINA_TRUE;
+}
+
+static void
+_tt_icon_replace_timed(void *data       __UNUSED__,
+                       Evas_Object     *obj,
+                       void *event_info __UNUSED__)
+{
+   Ecore_Timer *timer = evas_object_data_get(obj, "test-timer");
+   if (timer)
+     {
+        ecore_timer_del(timer);
+        evas_object_data_del(obj, "test-timer");
+        elm_button_label_set(obj, "Icon tooltip, click to start changed"
+                                  " timed");
+        return;
+     }
+
+   timer = ecore_timer_add(1.5, _tt_icon_replace_timer_cb, obj);
+   evas_object_data_set(obj, "test-timer", timer);
+   elm_button_label_set(obj, "Icon tooltip, click to stop changed timed");
+}
+
+static Eina_Bool
+_tt_style_replace_timer_cb(void *data)
+{
+   static int current = 0;
+   elm_object_tooltip_style_set(data, current ? NULL : "transparent");
+   current = !current;
+   return EINA_TRUE;
+}
+
+static void
+_tt_style_replace_timed(void *data       __UNUSED__,
+                        Evas_Object     *obj,
+                        void *event_info __UNUSED__)
+{
+   Ecore_Timer *timer = evas_object_data_get(obj, "test-timer");
+   if (timer)
+     {
+        ecore_timer_del(timer);
+        evas_object_data_del(obj, "test-timer");
+        elm_button_label_set(obj, "Icon tooltip style, click to start"
+                                  " changed timed");
+        return;
+     }
+
+   timer = ecore_timer_add(1.5, _tt_style_replace_timer_cb, obj);
+   evas_object_data_set(obj, "test-timer", timer);
+   elm_button_label_set(obj, "Icon tooltip style, click to stop changed"
+                             " timed");
+}
+
+static void
+_tt_visible_lock_toggle(void *data       __UNUSED__,
+                        Evas_Object     *obj,
+                        void *event_info __UNUSED__)
+{
+   static int locked = 0;
+
+   locked = !locked;
+   if (locked)
+     {
+        elm_button_label_set(obj, "Locked tooltip visibility");
+        elm_object_tooltip_text_set(obj, "This tooltip is locked"
+                                         " visible,<br> click the button"
+                                         " to unlock!");
+        elm_object_tooltip_show(obj);
+     }
+   else
+     {
+        elm_button_label_set(obj, "Unlocked tooltip visibility");
+        elm_object_tooltip_text_set(obj, "This tooltip is unlocked"
+                                         " visible,<br> click the button"
+                                         " to lock!");
+        elm_object_tooltip_hide(obj);
+     }
+}
+
+void
+test_tooltip(void *data       __UNUSED__,
+             Evas_Object *obj __UNUSED__,
+             void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *tb, *bt, *se, *lst;
+   Elm_Toolbar_Item *ti;
+   Elm_List_Item *li;
+
+   win = elm_win_add(NULL, "tooltip", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Tooltip");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   tb = elm_toolbar_add(win);
+   elm_toolbar_homogenous_set(tb, 0);
+   evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
+   elm_box_pack_end(bx, tb);
+   evas_object_show(tb);
+
+   ti = elm_toolbar_item_append(tb, NULL, "Open", NULL, NULL);
+   elm_toolbar_item_tooltip_text_set(ti, "Opens a file");
+
+   ti = elm_toolbar_item_append(tb, NULL, "Icon", NULL, NULL);
+   elm_toolbar_item_tooltip_content_cb_set
+     (ti, _tt_item_icon, (void *)456L, _tt_item_icon_del);
+   elm_toolbar_item_tooltip_style_set(ti, "transparent");
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Simple text tooltip");
+   elm_object_tooltip_text_set(bt, "Simple text tooltip");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Simple text tooltip, click to change");
+   elm_object_tooltip_text_set(bt, "Initial");
+   evas_object_smart_callback_add(bt, "clicked", _tt_text_replace, NULL);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Simple text tooltip, click to start"
+                            " changed timed");
+   elm_object_tooltip_text_set(bt, "Initial");
+   evas_object_smart_callback_add(bt, "clicked", _tt_text_replace_timed,
+                                  NULL);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_event_callback_add(bt, EVAS_CALLBACK_DEL, _tt_timer_del,
+                                  NULL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Icon tooltip");
+   elm_object_tooltip_content_cb_set(bt, _tt_icon, (void *)123L,
+                                     _tt_icon_del);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Icon tooltip, click to start changed timed");
+   elm_object_tooltip_content_cb_set(bt, _tt_icon, NULL, NULL);
+   evas_object_smart_callback_add(bt, "clicked", _tt_icon_replace_timed,
+                                  NULL);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_event_callback_add(bt, EVAS_CALLBACK_DEL, _tt_timer_del,
+                                  NULL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Transparent Icon tooltip");
+   elm_object_tooltip_content_cb_set(bt, _tt_icon, NULL, NULL);
+   elm_object_tooltip_style_set(bt, "transparent");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Icon tooltip style, click to start changed"
+                            " timed");
+   elm_object_tooltip_content_cb_set(bt, _tt_icon, NULL, NULL);
+   evas_object_smart_callback_add(bt, "clicked", _tt_style_replace_timed,
+                                  NULL);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_event_callback_add(bt, EVAS_CALLBACK_DEL, _tt_timer_del,
+                                  NULL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Unlocked tooltip visibility");
+   elm_object_tooltip_text_set(bt, "This tooltip is unlocked visible,<br>"
+                                   " click the button to lock!");
+   evas_object_smart_callback_add(bt, "clicked", _tt_visible_lock_toggle,
+                                  NULL);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+
+   se = elm_scrolled_entry_add(win);
+   evas_object_size_hint_weight_set(se, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(se, EVAS_HINT_FILL, 0.5);
+   elm_scrolled_entry_scrollbar_policy_set(se, ELM_SCROLLER_POLICY_OFF,
+                                           ELM_SCROLLER_POLICY_OFF);
+   elm_scrolled_entry_entry_set(se, "Hello, some scrolled entry here!");
+   elm_object_tooltip_text_set(se, "Type something here!");
+   elm_scrolled_entry_single_line_set(se, 1);
+   elm_box_pack_end(bx, se);
+   evas_object_show(se);
+
+   lst = elm_list_add(win);
+   li = elm_list_item_append(lst, "Hello", NULL, NULL, NULL, NULL);
+   elm_list_item_tooltip_text_set(li, "Something useful here?");
+   li = elm_list_item_append(lst, "Icon Tooltip", NULL, NULL, NULL, NULL);
+   elm_list_item_tooltip_content_cb_set(li, _tt_item_icon, NULL, NULL);
+   evas_object_size_hint_weight_set(lst, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(lst, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_min_set(lst, 100, 100);
+   elm_list_go(lst);
+   elm_box_pack_end(bx, lst);
+   evas_object_show(lst);
+
+   evas_object_resize(win, 320, 580);
+   evas_object_show(win);
+}
+
+void
+test_tooltip2(void *data       __UNUSED__,
+              Evas_Object *obj __UNUSED__,
+              void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *grid, *gl;
+   Elm_Genlist_Item *it1, *it2, *it3;
+   static Testitem ti[144];
+   int i, n;
+   char buf[PATH_MAX];
+   const char *img[9] =
+   {
+      "panel_01.jpg",
+      "plant_01.jpg",
+      "rock_01.jpg",
+      "rock_02.jpg",
+      "sky_01.jpg",
+      "sky_02.jpg",
+      "sky_03.jpg",
+      "sky_04.jpg",
+      "wood_01.jpg",
+   };
+
+   win = elm_win_add(NULL, "tooltip2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Tooltip 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   grid = elm_gengrid_add(win);
+   elm_gengrid_item_size_set(grid, 100, 100);
+   elm_gengrid_horizontal_set(grid, EINA_FALSE);
+   elm_gengrid_multi_select_set(grid, EINA_TRUE);
+   evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+
+   gic.item_style = "default";
+   gic.func.label_get = grdt_lbl_get;
+   gic.func.icon_get = grdt_icon_get;
+
+   n = 0;
+   for (i = 0; i < 9; i++)
+     {
+        snprintf(buf, sizeof(buf), "%s/images/%s", PACKAGE_DATA_DIR,
+                 img[n]);
+        n++;
+        ti[i].mode = i;
+        ti[i].path = eina_stringshare_add(buf);
+        ti[i].item = elm_gengrid_item_append(grid, &gic, &(ti[i]), NULL,
+                                             NULL);
+        if (n % 2)
+          elm_gengrid_item_tooltip_text_set(ti[i].item, "Testing X");
+        else
+          elm_gengrid_item_tooltip_text_set(ti[i].item, "Testing Y");
+        if (!(i % 5))
+          elm_gengrid_item_selected_set(ti[i].item, EINA_TRUE);
+     }
+
+   elm_box_pack_end(bx, grid);
+   evas_object_show(grid);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+
+   itct.item_style = "default";
+   itct.func.label_get = gltt_label_get;
+
+   it1 = elm_genlist_item_append(gl, &itct, (void *)1, NULL,
+                                 ELM_GENLIST_ITEM_SUBITEMS, NULL, NULL);
+   it2 = elm_genlist_item_append(gl, &itct, (void *)2, NULL,
+                                 ELM_GENLIST_ITEM_SUBITEMS, NULL, NULL);
+   it3 = elm_genlist_item_append(gl, &itct, (void *)3, NULL,
+                                 ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+   elm_genlist_item_tooltip_text_set(it1, "Testing 1");
+   elm_genlist_item_tooltip_text_set(it2, "Testing 2");
+   elm_genlist_item_tooltip_text_set(it3, "Testing 3");
+
+   evas_object_smart_callback_add(gl, "expand,request", gltt_exp_req, gl);
+   evas_object_smart_callback_add(gl, "contract,request", gltt_con_req,
+                                  gl);
+   evas_object_smart_callback_add(gl, "expanded", gltt_exp, gl);
+   evas_object_smart_callback_add(gl, "contracted", gltt_con, gl);
+
+   elm_box_pack_end(bx, gl);
+   evas_object_show(gl);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+
+#endif
diff --git a/src/bin/test_transit.c b/src/bin/test_transit.c
new file mode 100644 (file)
index 0000000..0067fc5
--- /dev/null
@@ -0,0 +1,524 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct _Custom_Effect Custom_Effect;
+
+struct _Custom_Effect
+{
+   struct _size
+     {
+        Evas_Coord w, h;
+     } from, to;
+};
+
+static void
+_custom_op(void *data, Elm_Transit *transit, double progress)
+{
+   if (!data) return;
+   Evas_Coord w, h;
+   Evas_Object *obj;
+   const Eina_List *elist;
+
+   Custom_Effect *custom_effect = data;
+   const Eina_List *objs = elm_transit_objects_get(transit);
+
+   if (progress < 0.5)
+     {
+        h = custom_effect->from.h + (custom_effect->to.h * progress * 2);
+        w = custom_effect->from.w;
+     }
+   else
+     {
+        h = custom_effect->from.h + custom_effect->to.h;
+        w = custom_effect->from.w + \
+            (custom_effect->to.w * (progress - 0.5) * 2);
+     }
+
+   EINA_LIST_FOREACH(objs, elist, obj)
+      evas_object_resize(obj, w, h);
+
+}
+
+static void *
+_custom_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
+{
+   Custom_Effect *custom_effect;
+
+   custom_effect = calloc(1, sizeof(Custom_Effect));
+   if (!custom_effect) return NULL;
+
+   custom_effect->from.w = from_w;
+   custom_effect->from.h = from_h;
+   custom_effect->to.w = to_w - from_w;
+   custom_effect->to.h = to_h - from_h;
+
+   return custom_effect;
+}
+
+static void
+_custom_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_transit_rotation_translation_color(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);
+   elm_transit_auto_reverse_set(trans, EINA_TRUE);
+   elm_transit_repeat_times_set(trans, 2);
+
+   /* Translation Effect */
+   elm_transit_effect_translation_add(trans, -70.0, -150.0, 70.0, 150.0);
+
+   /* Color Effect */
+   elm_transit_effect_color_add(trans, 100, 255, 100, 255, 200, 50, 200, 50); 
+
+   /* Rotation Effect */
+   elm_transit_effect_rotation_add(trans, 0.0, 135.0);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+static void
+_transit_wipe(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);
+   elm_transit_auto_reverse_set(trans, EINA_TRUE);
+
+   elm_transit_effect_wipe_add(trans, 
+                               ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE,
+                               ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+static void
+_transit_image_animation(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Eina_List *images = NULL;
+   char buf[PATH_MAX];
+   Elm_Transit *trans;
+   Evas_Object *ic = data;
+
+   snprintf(buf, sizeof(buf), "%s/images/icon_19.png", PACKAGE_DATA_DIR);
+   images = eina_list_append(images, eina_stringshare_add(buf));
+
+   snprintf(buf, sizeof(buf), "%s/images/icon_00.png", PACKAGE_DATA_DIR);
+   images = eina_list_append(images, eina_stringshare_add(buf));
+
+   snprintf(buf, sizeof(buf), "%s/images/icon_11.png", PACKAGE_DATA_DIR);
+   images = eina_list_append(images, eina_stringshare_add(buf));
+
+   snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   images = eina_list_append(images, eina_stringshare_add(buf));
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, ic);
+
+   elm_transit_effect_image_animation_add(trans, images);
+
+   elm_transit_duration_set(trans, 5.0); 
+   elm_transit_go(trans);
+}
+
+static void
+_transit_resizing(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);   
+
+   elm_transit_effect_resizing_add(trans, 100, 50, 300, 150);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+static void
+_transit_flip(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+   Evas_Object *obj2 = data;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);
+   elm_transit_object_add(trans, obj2);
+
+   elm_transit_effect_flip_add(trans, ELM_TRANSIT_EFFECT_FLIP_AXIS_X, EINA_TRUE);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+static void
+_transit_zoom(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);
+
+   elm_transit_effect_zoom_add(trans, 1.0, 3.0);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+static void
+_transit_blend(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+   Evas_Object *obj2 = data;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);
+   elm_transit_object_add(trans, obj2);
+
+   elm_transit_effect_blend_add(trans);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+static void
+_transit_fade(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+   Evas_Object *obj2 = data;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);
+   elm_transit_object_add(trans, obj2);
+
+   elm_transit_effect_fade_add(trans);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+static void
+_transit_resizable_flip(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *trans;
+   Evas_Object *obj2 = data;
+
+   trans = elm_transit_add();
+   elm_transit_object_add(trans, obj);
+   elm_transit_object_add(trans, obj2);
+
+   elm_transit_effect_resizable_flip_add(trans, ELM_TRANSIT_EFFECT_FLIP_AXIS_Y, EINA_TRUE);
+
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+/* Translation, Rotation, Color, Wipe, ImagemAnimation Effect */
+void
+test_transit(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bx, *bt, *ic;
+   char buf[PATH_MAX];
+
+   win = elm_win_add(NULL, "transit", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_min_set(bx, 318, 318);
+   evas_object_show(bx);
+
+   ic = elm_icon_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/icon_11.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "ImageAnimation Effect");
+   elm_button_icon_set(bt, ic);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_show(ic);
+   evas_object_smart_callback_add(bt, "clicked", _transit_image_animation, ic);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Color, Rotation and Translation");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_smart_callback_add(bt, "clicked",
+                                  _transit_rotation_translation_color, NULL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Wipe Effect");
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_smart_callback_add(bt, "clicked", _transit_wipe, NULL);
+
+   evas_object_show(win);
+}
+
+/* Resizing Effect */
+void
+test_transit2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bt;
+
+   win = elm_win_add(NULL, "transit-2", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit 2");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_resize(win, 400, 400);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Resizing Effect");
+   evas_object_show(bt);
+   evas_object_move(bt, 50, 100);
+   evas_object_resize(bt, 100, 50);
+   evas_object_smart_callback_add(bt, "clicked", _transit_resizing, NULL);
+
+   evas_object_show(win);
+}
+
+/* Flip Effect */
+void
+test_transit3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bt, *bt2;
+
+   win = elm_win_add(NULL, "transit-3", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit 3");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_resize(win, 300, 300);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Front Button - Flip Effect");
+   evas_object_show(bt);
+   evas_object_move(bt, 50, 50);
+   evas_object_resize(bt, 200, 200);
+
+   bt2 = elm_button_add(win);
+   elm_button_label_set(bt2, "Back Button - Flip Effect");
+   evas_object_move(bt2, 50, 50);
+   evas_object_resize(bt2, 200, 200);
+
+   evas_object_show(win);
+
+   evas_object_smart_callback_add(bt, "clicked", _transit_flip, bt2);
+   evas_object_smart_callback_add(bt2, "clicked", _transit_flip, bt);
+}
+
+/* Zoom Effect */
+void
+test_transit4(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bt;
+
+   win = elm_win_add(NULL, "transit-4", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit 4");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_resize(win, 300, 300);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Zoom Effect");
+   evas_object_resize(bt, 100, 50);
+   evas_object_move(bt, 100, 125); 
+   evas_object_show(bt);
+
+   evas_object_smart_callback_add(bt, "clicked", _transit_zoom, NULL);
+
+   evas_object_show(win);
+}
+
+/* Blend Effect */
+void
+test_transit5(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bt, *bt2, *ic;
+
+   win = elm_win_add(NULL, "transit-5", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit 5");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_resize(win, 300, 300);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   ic = elm_icon_add(win);
+   elm_icon_file_set(ic, PACKAGE_DATA_DIR"/images/rock_01.jpg", NULL);
+   evas_object_size_hint_max_set(ic, 50, 50);
+
+   bt = elm_button_add(win);
+   elm_button_icon_set(bt, ic);
+   elm_button_label_set(bt, "Before Button - Blend Effect");
+   evas_object_move(bt, 25, 125);
+   evas_object_resize(bt, 250, 50);    
+   evas_object_show(bt);
+
+   ic = elm_icon_add(win);
+   elm_icon_file_set(ic, PACKAGE_DATA_DIR"/images/rock_02.jpg", NULL);
+   evas_object_size_hint_max_set(ic, 50, 50);
+
+   bt2 = elm_button_add(win);
+   elm_button_icon_set(bt2, ic);
+   elm_button_label_set(bt2, "After Button - Blend Effect");
+   evas_object_move(bt2, 25, 125);
+   evas_object_resize(bt2, 250, 50);   
+
+   evas_object_show(win);
+
+   evas_object_smart_callback_add(bt, "clicked", _transit_blend, bt2);
+   evas_object_smart_callback_add(bt2, "clicked", _transit_blend, bt);
+}
+
+/* Fade Effect */
+void
+test_transit6(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bt, *bt2, *ic;
+
+   win = elm_win_add(NULL, "transit-6", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit 6");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_resize(win, 300, 300);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   ic = elm_icon_add(win);
+   elm_icon_file_set(ic, PACKAGE_DATA_DIR"/images/rock_01.jpg", NULL);
+   evas_object_size_hint_max_set(ic, 50, 50);
+
+   bt = elm_button_add(win);
+   elm_button_icon_set(bt, ic);
+   elm_button_label_set(bt, "Before Button - Fade Effect");
+   evas_object_move(bt, 25, 125);
+   evas_object_resize(bt, 250, 50);    
+   evas_object_show(bt);
+
+   ic = elm_icon_add(win);
+   elm_icon_file_set(ic, PACKAGE_DATA_DIR"/images/rock_02.jpg", NULL);
+   evas_object_size_hint_max_set(ic, 50, 50);
+
+   bt2 = elm_button_add(win);
+   elm_button_icon_set(bt2, ic);
+   elm_button_label_set(bt2, "After Button - Fade Effect");
+   evas_object_move(bt2, 25, 125);
+   evas_object_resize(bt2, 250, 50);   
+
+   evas_object_show(win);
+
+   evas_object_smart_callback_add(bt, "clicked", _transit_fade, bt2);
+   evas_object_smart_callback_add(bt2, "clicked", _transit_fade, bt);
+}
+
+/* Resizable Flip Effect */
+void
+test_transit7(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bt, *bt2;
+
+   win = elm_win_add(NULL, "transit-7", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit 7");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_resize(win, 400, 400);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Front Button - Resizable Flip Effect");
+   evas_object_show(bt);
+   evas_object_move(bt, 50, 100);
+   evas_object_resize(bt, 250, 30); 
+
+   bt2 = elm_button_add(win);
+   elm_button_label_set(bt2, "Back Button - Resizable Flip Effect");
+   evas_object_move(bt2, 50, 100);
+   evas_object_resize(bt2, 300, 200);
+
+   evas_object_show(win);
+
+   evas_object_smart_callback_add(bt, "clicked", _transit_resizable_flip, bt2);
+   evas_object_smart_callback_add(bt2, "clicked", _transit_resizable_flip, bt);
+}
+
+/* Custom Effect */
+void
+test_transit8(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *bt;
+   Elm_Transit *trans;
+   void *effect_context;
+
+   win = elm_win_add(NULL, "transit-8", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Transit 8");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_resize(win, 400, 400);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Button - Custom Effect");
+   evas_object_show(bt);
+   evas_object_move(bt, 50, 100);
+   evas_object_resize(bt, 250, 150);
+
+   evas_object_show(win);
+
+   /* Adding Transit */
+   trans = elm_transit_add();
+   elm_transit_auto_reverse_set(trans, EINA_TRUE);
+   elm_transit_tween_mode_set(trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
+   elm_transit_repeat_times_set(trans, -1);
+   effect_context = _custom_context_new(100, 100, 250, 250);
+   elm_transit_object_add(trans, bt);
+   elm_transit_effect_add(trans,
+                          _custom_op, effect_context,
+                          _custom_context_free);
+   elm_transit_duration_set(trans, 5.0);
+   elm_transit_go(trans);
+}
+
+#endif
diff --git a/src/bin/test_weather.c b/src/bin/test_weather.c
new file mode 100644 (file)
index 0000000..536bd32
--- /dev/null
@@ -0,0 +1,176 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+
+#ifdef HAVE_ELEMENTARY_EWEATHER
+# include "EWeather_Smart.h"
+#endif
+
+#ifdef HAVE_ELEMENTARY_EWEATHER
+static Evas_Object *en, *hv, *fl;
+static Evas_Object *weather[2];
+static int current = 0;
+static Eina_Module *module[2];
+
+static void
+_first_city_cb(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   if (!current) return;
+   current = 0;
+   elm_flip_go(fl, ELM_FLIP_ROTATE_YZ_CENTER_AXIS);
+}
+
+static void
+_second_city_cb(void *dat __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   if (current) return;
+   current = 1;
+   elm_flip_go(fl, ELM_FLIP_ROTATE_XZ_CENTER_AXIS);
+}
+
+static void _apply_cb(void *data __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   EWeather *eweather = eweather_object_eweather_get(weather[current]);
+
+   if (module[current])
+     eweather_plugin_set(eweather, module[current]);
+   eweather_code_set(eweather, elm_entry_entry_get(en));
+   printf("CURRENT %d %p %p\n", current, module[current], eweather);
+}
+
+static void
+_hover_select_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   EWeather *eweather = eweather_object_eweather_get(weather[0]);
+   module[0] = eweather_plugin_search(eweather, elm_hoversel_item_label_get(event_info));
+
+   eweather = eweather_object_eweather_get(weather[1]);
+   module[1] = eweather_plugin_search(eweather, elm_hoversel_item_label_get(event_info));
+   printf("%p %p\n", module[0], module[1]);
+}
+#endif
+
+void
+test_weather(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg;
+#ifdef HAVE_ELEMENTARY_EWEATHER
+   Evas_Object *bx, *bx0, *bt;
+   EWeather *eweather;
+   Eina_Array_Iterator it;
+   Eina_Array *array;
+   Eina_Module *m;
+   unsigned int i;
+#endif
+
+   win = elm_win_add(NULL, "weather", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Weather");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bg);
+   evas_object_show(bg);
+
+#ifdef HAVE_ELEMENTARY_EWEATHER 
+   bx = elm_box_add(win);
+   elm_win_resize_object_add(win, bx);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+
+   fl = elm_flip_add(win);
+   evas_object_size_hint_align_set(fl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(fl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, fl);
+
+   current = 0;
+
+   module[0] = NULL;
+   weather[0] = eweather_object_add(evas_object_evas_get(win));
+   evas_object_size_hint_weight_set(weather[0], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(weather[0], -1.0, -1.0);
+   elm_flip_content_front_set(fl, weather[0]);
+   evas_object_show(weather[0]);
+
+   module[1] = NULL;
+   weather[1] = eweather_object_add(evas_object_evas_get(win));
+   eweather = eweather_object_eweather_get(weather[1]);
+   evas_object_size_hint_weight_set(weather[1], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(weather[1], -1.0, -1.0);
+   elm_flip_content_back_set(fl, weather[1]);
+   evas_object_show(weather[1]);
+
+   evas_object_show(fl);
+
+   //
+   bx0 = elm_box_add(win);
+   elm_box_horizontal_set(bx0, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx0, 1.0, 0.0);
+   elm_box_pack_end(bx, bx0);
+   evas_object_show(bx0);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "First city");
+   evas_object_show(bt);
+   elm_box_pack_end(bx0, bt);
+   evas_object_smart_callback_add(bt, "clicked", _first_city_cb, NULL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Second city");
+   evas_object_show(bt);
+   elm_box_pack_end(bx0, bt);
+   evas_object_smart_callback_add(bt, "clicked", _second_city_cb, NULL);
+   //
+
+   //
+   bx0 = elm_box_add(win);
+   elm_box_horizontal_set(bx0, EINA_TRUE);
+   evas_object_size_hint_weight_set(bx0, 1.0, 0.0);
+   elm_box_pack_end(bx, bx0);
+   evas_object_show(bx0);
+
+   hv = elm_hoversel_add(win);
+   elm_hoversel_hover_parent_set(hv, win);
+   elm_hoversel_label_set(hv, "data source");
+   evas_object_size_hint_weight_set(hv, 0.0, 0.0);
+   evas_object_size_hint_align_set(hv, 0.5, 0.5);
+   elm_box_pack_end(bx0, hv);
+   evas_object_show(hv);
+
+   array = eweather_plugins_list_get(eweather);
+
+   EINA_ARRAY_ITER_NEXT(array, i, m, it)
+     elm_hoversel_item_add(hv, eweather_plugin_name_get(eweather, i), NULL, ELM_ICON_NONE, _hover_select_cb, NULL);
+
+   en = elm_entry_add(win);
+   elm_entry_line_wrap_set(en, 0);
+   elm_entry_single_line_set(en, EINA_TRUE);
+   elm_entry_entry_set(en, "Paris");
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx0, en);
+   evas_object_show(en);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Apply");
+   evas_object_show(bt);
+   elm_box_pack_end(bx0, bt);
+   evas_object_smart_callback_add(bt, "clicked", _apply_cb, NULL);
+   //
+
+
+#else
+    Evas_Object *lbl;
+    
+    lbl = elm_label_add(win);
+    elm_win_resize_object_add(win, lbl);
+    elm_label_label_set(lbl, "libeweather is required to display the forecast.");
+    evas_object_show(lbl);
+#endif
+
+    evas_object_resize(win, 244, 388);
+    evas_object_show(win);
+}
+#endif
diff --git a/src/bin/test_win_state.c b/src/bin/test_win_state.c
new file mode 100644 (file)
index 0000000..d6efacb
--- /dev/null
@@ -0,0 +1,369 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifndef ELM_LIB_QUICKLAUNCH
+typedef struct _Testitem
+{
+   Elm_Genlist_Item *item;
+   int mode, onoff;
+} Testitem;
+
+static int rotate_with_resize = 0;
+
+static void
+my_bt_38_alpha_on(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *bg = evas_object_data_get(win, "bg");
+   evas_object_hide(bg);
+   elm_win_alpha_set(win, 1);
+}
+
+static void
+my_bt_38_alpha_off(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   Evas_Object *bg = evas_object_data_get(win, "bg");
+   evas_object_show(bg);
+   elm_win_alpha_set(win, 0);
+}
+
+static void
+my_ck_38_resize(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+//   Evas_Object *win = data;
+   rotate_with_resize = elm_check_state_get(obj);
+}
+
+static void
+my_bt_38_rot_0(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   if (rotate_with_resize)
+     elm_win_rotation_with_resize_set(win, 0);
+   else        
+     elm_win_rotation_set(win, 0);
+}
+
+static void
+my_bt_38_rot_90(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   if (rotate_with_resize)
+     elm_win_rotation_with_resize_set(win, 90);
+   else        
+     elm_win_rotation_set(win, 90);
+}
+
+static void
+my_bt_38_rot_180(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   if (rotate_with_resize)
+     elm_win_rotation_with_resize_set(win, 180);
+   else        
+     elm_win_rotation_set(win, 180);
+}
+
+static void
+my_bt_38_rot_270(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = data;
+   if (rotate_with_resize)
+     elm_win_rotation_with_resize_set(win, 270);
+   else        
+     elm_win_rotation_set(win, 270);
+}
+
+static void
+my_win_move(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Coord x, y;
+   elm_win_screen_position_get(obj, &x, &y);
+   printf("MOVE - win geom: %4i %4i\n", x, y);
+}
+
+static void
+_win_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Coord w, h;
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   printf("RESIZE - win geom: %4ix%4i\n", w, h);
+}
+
+static void
+_win_foc_in(void *data __UNUSED__, Evas *e __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("FOC IN\n");
+}
+
+static void
+_win_foc_out(void *data __UNUSED__, Evas *e __UNUSED__, void *event_info __UNUSED__)
+{
+   printf("FOC OUT\n");
+}
+
+static void
+_close_win(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_del(data);
+}
+
+void
+test_win_state(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *sl, *bx, *bx2, *bt, *ck;
+
+   win = elm_win_add(NULL, "window-state", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Window States");
+   evas_object_smart_callback_add(win, "moved", my_win_move, NULL);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, _win_resize, NULL);
+   evas_event_callback_add(evas_object_evas_get(win), EVAS_CALLBACK_CANVAS_FOCUS_IN, _win_foc_in, NULL);
+   evas_event_callback_add(evas_object_evas_get(win), EVAS_CALLBACK_CANVAS_FOCUS_OUT, _win_foc_out, NULL);
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+   evas_object_data_set(win, "bg", bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_fill_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Alpha On");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_alpha_on, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Alpha Off");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_alpha_off, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   sl = elm_slider_add(win);
+   elm_slider_label_set(sl, "Test");
+   elm_slider_span_size_set(sl, 100);
+   evas_object_size_hint_align_set(sl, 0.5, 0.5);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%3.0f");
+   elm_slider_min_max_set(sl, 50, 150);
+   elm_slider_value_set(sl, 50);
+   elm_slider_inverted_set(sl, 1);
+   elm_box_pack_end(bx2, sl);
+   evas_object_show(sl);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "resize");
+   elm_check_state_set(ck, rotate_with_resize);
+   evas_object_smart_callback_add(ck, "changed", my_ck_38_resize, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.02, 0.99);
+   evas_object_show(ck); 
+   elm_box_pack_end(bx, ck);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_fill_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 0");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_0, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 90");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_90, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 180");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_180, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 270");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_270, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 280, 400);
+   evas_object_show(win);
+}
+
+void
+test_win_state2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *sl, *bx, *bx2, *bt, *ck;
+   char buf[PATH_MAX];
+   
+   win = elm_win_add(NULL, "window-state2", ELM_WIN_BASIC);
+   elm_win_override_set(win, 1);
+   evas_object_smart_callback_add(win, "moved", my_win_move, NULL);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, _win_resize, NULL);
+   elm_win_title_set(win, "Window States 2");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   snprintf(buf, sizeof(buf), "%s/images/sky_02.jpg", PACKAGE_DATA_DIR);
+   elm_bg_file_set(bg, buf, NULL);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+   evas_object_data_set(win, "bg", bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_fill_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Alpha On");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_alpha_on, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Alpha Off");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_alpha_off, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, 0.0, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Close");
+   evas_object_smart_callback_add(bt, "clicked", _close_win, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   sl = elm_slider_add(win);
+   elm_slider_label_set(sl, "Override Redirect");
+   elm_slider_span_size_set(sl, 100);
+   evas_object_size_hint_align_set(sl, 0.5, 0.5);
+   evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_slider_indicator_format_set(sl, "%3.0f");
+   elm_slider_min_max_set(sl, 50, 150);
+   elm_slider_value_set(sl, 50);
+   elm_slider_inverted_set(sl, 1);
+   elm_box_pack_end(bx2, sl);
+   evas_object_show(sl);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   ck = elm_check_add(win);
+   elm_check_label_set(ck, "resize");
+   elm_check_state_set(ck, rotate_with_resize);
+   evas_object_smart_callback_add(ck, "changed", my_ck_38_resize, win);
+   evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(ck, 0.02, 0.99);
+   evas_object_show(ck); 
+   elm_box_pack_end(bx, ck);
+
+   bx2 = elm_box_add(win);
+   elm_box_horizontal_set(bx2, 1);
+   elm_box_homogenous_set(bx2, 1);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_fill_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 0");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_0, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 90");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_90, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 180");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_180, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   bt = elm_button_add(win);
+   elm_button_label_set(bt, "Rot 270");
+   evas_object_smart_callback_add(bt, "clicked", my_bt_38_rot_270, win);
+   evas_object_size_hint_fill_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx2, bt);
+   evas_object_show(bt);
+
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+}
+#endif
diff --git a/src/edje_externals/Makefile.am b/src/edje_externals/Makefile.am
new file mode 100644 (file)
index 0000000..8d1b53d
--- /dev/null
@@ -0,0 +1,61 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-DELM_INTERAL_API_MDFGELQ=1 \
+-I. \
+-I$(top_builddir) \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/lib \
+-I$(top_builddir)/src/lib \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+@ELEMENTARY_CFLAGS@ \
+@ELEMENTARY_X_CFLAGS@ \
+@ELEMENTARY_FB_CFLAGS@ \
+@ELEMENTARY_WIN32_CFLAGS@ \
+@ELEMENTARY_WINCE_CFLAGS@ \
+@ELEMENTARY_EDBUS_CFLAGS@ \
+@ELEMENTARY_EFREET_CFLAGS@ \
+@ELEMENTARY_ETHUMB_CFLAGS@
+
+if ELEMENTARY_WINDOWS_BUILD
+AM_CPPFLAGS += -DELEMENTARY_BUILD
+endif
+
+pkgdir = $(libdir)/edje/modules/elm/$(MODULE_EDJE)
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = private.h \
+modules.inc \
+elm.c \
+elm_anchorblock.c \
+elm_anchorview.c \
+elm_bubble.c \
+elm_button.c \
+elm_check.c \
+elm_clock.c \
+elm_fileselector.c \
+elm_fileselector_button.c \
+elm_fileselector_entry.c \
+elm_genlist.c \
+elm_hoversel.c \
+elm_list.c \
+elm_map.c \
+elm_photocam.c \
+elm_progressbar.c \
+elm_radio.c \
+elm_scrolled_entry.c \
+elm_slider.c \
+elm_slideshow.c \
+elm_spinner.c \
+elm_thumb.c \
+elm_toggle.c \
+elm_toolbar.c \
+elm_notify.c \
+elm_panes.c \
+elm_label.c \
+elm_icon.c \
+elm_scroller.c
+
+module_la_LIBADD = $(top_builddir)/src/lib/libelementary.la
+module_la_LDFLAGS = -no-undefined -module -avoid-version -shared -fPIC
diff --git a/src/edje_externals/elm.c b/src/edje_externals/elm.c
new file mode 100644 (file)
index 0000000..ccb6069
--- /dev/null
@@ -0,0 +1,300 @@
+#include "Elementary.h"
+#include "private.h"
+
+int _elm_log_dom = -1;
+
+static int init_count = 0;
+
+void
+external_elm_init(void)
+{
+   int argc = 0;
+   char **argv = NULL;
+
+   init_count++;
+   printf("elm_real_init\n");
+   if (init_count > 1) return;
+   ecore_app_args_get(&argc, &argv);
+   elm_init(argc, argv);
+}
+
+static void
+external_elm_shutdown(void)
+{
+   init_count--;
+   printf("elm_real_shutdown\n");
+   if (init_count > 1) return;
+   elm_shutdown();
+}
+
+static void
+_external_obj_del(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, 
+                                  _external_obj_del);
+   external_elm_shutdown();
+}
+
+void
+external_signal(void *data __UNUSED__, Evas_Object *obj, const char *signal, const char *source)
+{
+       char *_signal = strdup(signal);
+       char *p = _signal;
+       Evas_Object *content;
+
+       while((*p!='\0') && (*p!=']'))
+               p++;
+
+
+       if((*p=='\0') || (*(p+1)!=':'))
+       {
+               ERR("Invalid External Signal received: '%s' '%s'\n", signal, source);
+               free(_signal);
+               return ;
+       }
+
+       *p = '\0';
+       p+=2; //jump ']' and ':'
+
+       Edje_External_Type *type = evas_object_data_get(obj, "Edje_External_Type");
+       if (!type->content_get)
+       {
+               ERR("external type '%s' from module '%s' does not provide content_get()",
+                               type->module_name, type->module);
+               free(_signal);
+               return ;
+       }
+
+       content = type->content_get(type->data, obj, _signal);
+       free(_signal);
+       if(content)
+               edje_object_signal_emit(content, signal + (p - _signal), source);
+}
+
+const char *
+external_translate(void *data __UNUSED__, const char *orig)
+{
+   // in future, mark all params as translatable and use dgettext()
+   // with "elementary" text domain here.
+   return orig;
+}
+
+typedef struct {
+   const char *emission;
+   const char *source;
+   Evas_Object *edje;
+} Elm_External_Signals_Proxy_Context;
+
+static void
+_external_signal_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_External_Signals_Proxy_Context *ctxt = data;
+   free(ctxt);
+}
+
+static void
+_external_signal_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_External_Signals_Proxy_Context *ctxt = data;
+   // TODO: Is it worth to check Evas_Smart_Cb_Description and do something
+   // TODO: with event_info given its description?
+   edje_object_signal_emit(ctxt->edje, ctxt->emission, ctxt->source);
+}
+
+Eina_Bool
+external_common_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "style"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+          {
+             param->s = elm_object_style_get(obj);
+             return EINA_TRUE;
+          }
+     }
+   return EINA_FALSE;
+}
+
+Eina_Bool
+external_common_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "style"))
+     {
+         if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+           {
+              elm_object_style_set(obj, param->s);
+              return EINA_TRUE;
+           }
+     }
+   return EINA_FALSE;
+}
+
+void
+external_signals_proxy(Evas_Object *obj, Evas_Object *edje, const char *part_name)
+{
+   const Evas_Smart_Cb_Description **cls_descs, **inst_descs;
+   unsigned int cls_count, inst_count, total;
+   Elm_External_Signals_Proxy_Context *ctxt;
+
+   evas_object_smart_callbacks_descriptions_get
+     (obj, &cls_descs, &cls_count, &inst_descs, &inst_count);
+
+   total = cls_count + inst_count;
+   if (!total) return;
+   ctxt = malloc(sizeof(Elm_External_Signals_Proxy_Context) * total);
+   if (!ctxt) return;
+   evas_object_event_callback_add
+     (obj, EVAS_CALLBACK_DEL, _external_signal_proxy_free_cb, ctxt);
+
+   for (; cls_count > 0; cls_count--,  cls_descs++, ctxt++)
+     {
+       const Evas_Smart_Cb_Description *d = *cls_descs;
+       ctxt->emission = d->name;
+       ctxt->source = part_name;
+       ctxt->edje = edje;
+       evas_object_smart_callback_add
+         (obj, d->name, _external_signal_proxy_cb, ctxt);
+     }
+
+   for (; inst_count > 0; inst_count--,  inst_descs++, ctxt++)
+     {
+       const Evas_Smart_Cb_Description *d = *inst_descs;
+       ctxt->emission = d->name;
+       ctxt->source = part_name;
+       ctxt->edje = edje;
+       evas_object_smart_callback_add
+         (obj, d->name, _external_signal_proxy_cb, ctxt);
+     }
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, 
+                                  _external_obj_del, NULL);
+}
+
+void
+external_common_params_parse(void *mem, void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params *p;
+   const Eina_List *l;
+   Edje_External_Param *param;
+
+   p = mem;
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "style"))
+          {
+             p->style = eina_stringshare_add(param->s);
+             break;
+          }
+     }
+}
+
+void
+external_common_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params *p;
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->style)
+      elm_object_style_set(obj, p->style);
+}
+
+Evas_Object *
+external_common_param_icon_get(Evas_Object *obj, const Edje_External_Param *p)
+{
+   Evas_Object *edje, *parent_widget, *icon;
+   const char *file;
+
+   if ((!p) || (!p->s) || (p->type != EDJE_EXTERNAL_PARAM_TYPE_STRING))
+       return NULL;
+
+   edje = evas_object_smart_parent_get(obj);
+   edje_object_file_get(edje, &file, NULL);
+
+   parent_widget = elm_widget_parent_widget_get(obj);
+   if (!parent_widget)
+     parent_widget = edje;
+   icon = elm_icon_add(parent_widget);
+
+   if (elm_icon_file_set(icon, file, p->s))
+     return icon;
+   if (elm_icon_standard_set(icon, p->s))
+     return icon;
+
+   evas_object_del(icon);
+   return NULL;
+}
+
+void
+external_common_icon_param_parse(Evas_Object **icon, Evas_Object *obj, const Eina_List *params)
+{
+   Edje_External_Param *p = edje_external_param_find(params, "icon");
+   *icon = external_common_param_icon_get(obj, p);
+}
+
+Evas_Object *
+external_common_param_edje_object_get(Evas_Object *obj, const Edje_External_Param *p)
+{
+   Evas_Object *edje, *parent_widget, *ret;
+   const char *file;
+
+   if ((!p) || (!p->s) || (p->type != EDJE_EXTERNAL_PARAM_TYPE_STRING))
+       return NULL;
+
+   edje = evas_object_smart_parent_get(obj);
+   edje_object_file_get(edje, &file, NULL);
+
+   parent_widget = elm_widget_parent_widget_get(obj);
+   if (!parent_widget)
+     parent_widget = edje;
+
+   ret = edje_object_add(evas_object_evas_get(parent_widget));
+
+   if (edje_object_file_set(ret, file, p->s))
+     return ret;
+
+   evas_object_del(ret);
+   return NULL;
+}
+
+void
+external_common_params_free(void *params)
+{
+   Elm_Params *p = params;
+   if (p->style)
+     eina_stringshare_del(p->style);
+}
+
+#define DEFINE_TYPE(type_name) \
+  extern const Edje_External_Type external_##type_name##_type;
+#include "modules.inc"
+#undef DEFINE_TYPE
+
+static Edje_External_Type_Info elm_external_types[] =
+{
+#define DEFINE_TYPE(type_name)              \
+  {"elm/"#type_name, &external_##type_name##_type},
+#include "modules.inc"
+#undef DEFINE_TYPE
+   {NULL, NULL}
+};
+
+static Eina_Bool
+elm_mod_init(void)
+{
+   _elm_log_dom = eina_log_domain_register("elm-externals", EINA_COLOR_LIGHTBLUE);
+   edje_external_type_array_register(elm_external_types);
+   return EINA_TRUE;
+}
+
+static void
+elm_mod_shutdown(void)
+{
+   edje_external_type_array_unregister(elm_external_types);
+   eina_log_domain_unregister(_elm_log_dom);
+   _elm_log_dom = -1;
+
+}
+
+EINA_MODULE_INIT(elm_mod_init);
+EINA_MODULE_SHUTDOWN(elm_mod_shutdown);
diff --git a/src/edje_externals/elm_anchorblock.c b/src/edje_externals/elm_anchorblock.c
new file mode 100644 (file)
index 0000000..1e04c37
--- /dev/null
@@ -0,0 +1,104 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Anchorblock
+{
+   Elm_Params base;
+   const char *text;
+} Elm_Params_Anchorblock;
+
+static void
+external_anchorblock_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Anchorblock *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->text)
+     {
+       elm_anchorblock_text_set(obj, p->text);
+     }
+}
+
+static Eina_Bool
+external_anchorblock_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "text"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_anchorblock_text_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_anchorblock_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "text"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_anchorblock_text_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_anchorblock_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Anchorblock *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = ELM_NEW(Elm_Params_Anchorblock);
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "text"))
+         mem->text = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_anchorblock_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_anchorblock_params_free(void *params)
+{
+   Elm_Params_Anchorblock *mem = params;
+
+   if (mem->text)
+     eina_stringshare_del(mem->text);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_anchorblock_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("text", "some text"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(anchorblock, "anchorblock")
+DEFINE_EXTERNAL_TYPE_SIMPLE(anchorblock, "Anchorblock");
diff --git a/src/edje_externals/elm_anchorview.c b/src/edje_externals/elm_anchorview.c
new file mode 100644 (file)
index 0000000..d74a09f
--- /dev/null
@@ -0,0 +1,104 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Anchorview
+{
+   Elm_Params base;
+   const char *text;
+} Elm_Params_Anchorview;
+
+static void
+external_anchorview_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Anchorview *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->text)
+     {
+       elm_anchorview_text_set(obj, p->text);
+     }
+}
+
+static Eina_Bool
+external_anchorview_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "text"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_anchorview_text_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_anchorview_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "text"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_anchorview_text_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_anchorview_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Anchorview *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = ELM_NEW(Elm_Params_Anchorview);
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "text"))
+         mem->text = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_anchorview_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_anchorview_params_free(void *params)
+{
+   Elm_Params_Anchorview *mem = params;
+
+   if (mem->text)
+     eina_stringshare_del(mem->text);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_anchorview_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("text", "some text"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(anchorview, "anchorview")
+DEFINE_EXTERNAL_TYPE_SIMPLE(anchorview, "Anchorview");
diff --git a/src/edje_externals/elm_bubble.c b/src/edje_externals/elm_bubble.c
new file mode 100644 (file)
index 0000000..1de2e82
--- /dev/null
@@ -0,0 +1,165 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Bubble
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+   const char *info;
+   Evas_Object *content; /* part name whose obj is to be set as content */
+} Elm_Params_Bubble;
+
+static void
+external_bubble_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Bubble *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label) elm_bubble_label_set(obj, p->label);
+   if (p->icon) elm_bubble_icon_set(obj, p->icon);
+   if (p->info) elm_bubble_info_set(obj, p->info);
+   if (p->content) elm_bubble_content_set(obj, p->content);
+}
+
+static Eina_Bool
+external_bubble_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_bubble_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_bubble_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "info"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_bubble_info_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "content"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *content = \
+                   external_common_param_edje_object_get(obj, param);
+            if ((strcmp(param->s, "")) && (!content)) return EINA_FALSE;
+            elm_bubble_content_set(obj, content);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_bubble_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_bubble_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "info"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_bubble_info_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "content"))
+     {
+       /* not easy to get content name back from live object */
+       return EINA_FALSE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_bubble_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_Bubble *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Bubble));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "info"))
+         mem->info = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "content"))
+         mem->content = external_common_param_edje_object_get(obj, param);
+       else if (!strcmp(param->name, "label"))
+         mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_bubble_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_bubble_params_free(void *params)
+{
+   Elm_Params_Bubble *mem = params;
+
+   if (mem->info)
+     eina_stringshare_del(mem->info);
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_bubble_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("info"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("content"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(bubble, "bubble");
+DEFINE_EXTERNAL_TYPE_SIMPLE(bubble, "Bubble");
diff --git a/src/edje_externals/elm_button.c b/src/edje_externals/elm_button.c
new file mode 100644 (file)
index 0000000..9e2f5c2
--- /dev/null
@@ -0,0 +1,125 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Button
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+} Elm_Params_Button;
+
+static void
+external_button_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Button *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_button_label_set(obj, p->label);
+   if (p->icon)
+     elm_button_icon_set(obj, p->icon);
+}
+
+static Eina_Bool
+external_button_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_button_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_button_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_button_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_button_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_button_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_Button *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = ELM_NEW(Elm_Params_Button);
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "label"))
+          {
+             mem->label = eina_stringshare_add(param->s);
+             break;
+          }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_button_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_button_params_free(void *params)
+{
+   Elm_Params_Button *mem = params;
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_button_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(button, "button");
+DEFINE_EXTERNAL_TYPE_SIMPLE(button, "Button");
diff --git a/src/edje_externals/elm_check.c b/src/edje_externals/elm_check.c
new file mode 100644 (file)
index 0000000..f9b3e8b
--- /dev/null
@@ -0,0 +1,148 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Check
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+   Eina_Bool state:1;
+   Eina_Bool state_exists:1;
+} Elm_Params_Check;
+
+static void
+external_check_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Check *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_check_label_set(obj, p->label);
+   if (p->icon)
+     elm_check_icon_set(obj, p->icon);
+   if (p->state_exists)
+     elm_check_state_set(obj, p->state);
+}
+
+static Eina_Bool
+external_check_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_check_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_check_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "state"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_check_state_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_check_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_check_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "state"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_check_state_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_check_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_Check *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Check));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "state"))
+          {
+             mem->state = !!param->i;
+             mem->state_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "label"))
+           mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_check_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_check_params_free(void *params)
+{
+   Elm_Params_Check *mem = params;
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_check_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL_FULL("state", 0, "unchecked", "checked"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(check, "check")
+DEFINE_EXTERNAL_TYPE_SIMPLE(check, "Check")
diff --git a/src/edje_externals/elm_clock.c b/src/edje_externals/elm_clock.c
new file mode 100644 (file)
index 0000000..c4bf9d2
--- /dev/null
@@ -0,0 +1,241 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Clock
+{
+   Elm_Params base;
+   int hrs, min, sec;
+   Eina_Bool hrs_exists:1;
+   Eina_Bool min_exists:1;
+   Eina_Bool sec_exists:1;
+   Eina_Bool edit:1;
+   Eina_Bool ampm:1;
+   Eina_Bool seconds:1;
+} Elm_Params_Clock;
+
+static void
+external_clock_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Clock *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if ((p->hrs_exists) && (p->min_exists) && (p->sec_exists))
+     elm_clock_time_set(obj, p->hrs, p->min, p->sec);
+   else if ((p->hrs_exists) || (p->min_exists) || (p->sec_exists))
+     {
+       int hrs, min, sec;
+       elm_clock_time_get(obj, &hrs, &min, &sec);
+       if (p->hrs_exists)
+         hrs = p->hrs;
+       if (p->min_exists)
+         min = p->min;
+       if (p->sec_exists)
+         sec = p->sec;
+       elm_clock_time_set(obj, hrs, min, sec);
+     }
+   if (p->edit)
+     elm_clock_edit_set(obj, p->edit);
+   if (p->ampm)
+     elm_clock_show_am_pm_set(obj, p->ampm);
+   if (p->seconds)
+     elm_clock_show_seconds_set(obj, p->seconds);
+}
+
+static Eina_Bool
+external_clock_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "hours"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            int hrs, min, sec;
+            elm_clock_time_get(obj, &hrs, &min, &sec);
+            elm_clock_time_set(obj, param->d, min, sec);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "minutes"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            int hrs, min, sec;
+            elm_clock_time_get(obj, &hrs, &min, &sec);
+            elm_clock_time_set(obj, hrs, param->d, sec);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "seconds"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            int hrs, min, sec;
+            elm_clock_time_get(obj, &hrs, &min, &sec);
+            elm_clock_time_set(obj, hrs, min, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "editable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_clock_edit_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "am/pm"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_clock_show_am_pm_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "show seconds"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_clock_show_seconds_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_clock_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "hours"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            int hrs, min, sec;
+            elm_clock_time_get(obj, &hrs, &min, &sec);
+            param->i = hrs;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "minutes"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            int hrs, min, sec;
+            elm_clock_time_get(obj, &hrs, &min, &sec);
+            param->i = min;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "seconds"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            int hrs, min, sec;
+            elm_clock_time_get(obj, &hrs, &min, &sec);
+            param->i = sec;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "editable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_clock_edit_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "am/pm"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_clock_show_am_pm_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "show seconds"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_clock_show_seconds_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_clock_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Clock *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Clock));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "hours"))
+         {
+            mem->hrs = param->i;
+            mem->hrs_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "minutes"))
+         {
+            mem->min = param->i;
+            mem->min_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "seconds"))
+         {
+            mem->sec = param->i;
+            mem->sec_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "editable"))
+         mem->edit = !!param->i;
+       else if (!strcmp(param->name, "am/pm"))
+         mem->ampm = !!param->i;
+       else if (!strcmp(param->name, "show seconds"))
+         mem->seconds = !!param->i;
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_clock_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_clock_params_free(void *params)
+{
+   Elm_Params_Clock *mem = params;
+
+   free(mem);
+}
+
+static Edje_External_Param_Info external_clock_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_INT("hours"),
+   EDJE_EXTERNAL_PARAM_INFO_INT("minutes"),
+   EDJE_EXTERNAL_PARAM_INFO_INT("seconds"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("editable"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("am/pm"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("show seconds"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(clock, "clock")
+DEFINE_EXTERNAL_TYPE_SIMPLE(clock, "Clock")
diff --git a/src/edje_externals/elm_fileselector.c b/src/edje_externals/elm_fileselector.c
new file mode 100644 (file)
index 0000000..246698c
--- /dev/null
@@ -0,0 +1,185 @@
+#include <assert.h>
+
+#include "private.h"
+
+typedef struct _Elm_Params_Fileselector
+{
+   Elm_Params base;
+   Eina_Bool is_save:1;
+   Eina_Bool is_save_set:1;
+   Eina_Bool folder_only:1;
+   Eina_Bool folder_only_set:1;
+   Eina_Bool show_buttons:1;
+   Eina_Bool show_buttons_set:1;
+   Eina_Bool expandable:1;
+   Eina_Bool expandable_set:1;
+} Elm_Params_Fileselector;
+
+static void
+external_fileselector_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Fileselector *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if ((p->is_save_set) && (p->is_save))
+     elm_fileselector_is_save_set(obj, p->is_save);
+   if (p->folder_only_set)
+     elm_fileselector_folder_only_set(obj, p->folder_only);
+   if (p->show_buttons_set)
+     elm_fileselector_buttons_ok_cancel_set(obj, p->show_buttons);
+   if (p->expandable_set)
+     elm_fileselector_expandable_set(obj, p->expandable);
+}
+
+static Eina_Bool
+external_fileselector_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "save"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_is_save_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "folder only"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_folder_only_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "show buttons"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_buttons_ok_cancel_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "expandable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_expandable_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_fileselector_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "save"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_is_save_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "folder only"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_folder_only_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "show buttons"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_buttons_ok_cancel_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "expandable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_expandable_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_fileselector_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Fileselector *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Fileselector));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "save"))
+         {
+            mem->is_save = !!param->i;
+            mem->is_save_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "folder only"))
+         {
+            mem->folder_only = !!param->i;
+            mem->folder_only_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "show buttons"))
+         {
+            mem->show_buttons = !!param->i;
+            mem->show_buttons_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "expandable"))
+         {
+            mem->expandable = !!param->i;
+            mem->expandable_set = EINA_TRUE;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_fileselector_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+   ERR("No content.");
+   return NULL;
+}
+
+static void
+external_fileselector_params_free(void *params)
+{
+   Elm_Params_Fileselector *mem = params;
+   free(mem);
+}
+
+static Edje_External_Param_Info external_fileselector_params[] =
+  {
+    DEFINE_EXTERNAL_COMMON_PARAMS,
+    EDJE_EXTERNAL_PARAM_INFO_BOOL("save"),
+    EDJE_EXTERNAL_PARAM_INFO_BOOL("folder only"),
+    EDJE_EXTERNAL_PARAM_INFO_BOOL("show buttons"),
+    EDJE_EXTERNAL_PARAM_INFO_BOOL("expandable"),
+    EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+  };
+
+DEFINE_EXTERNAL_ICON_ADD(fileselector, "fileselector")
+DEFINE_EXTERNAL_TYPE_SIMPLE(fileselector, "File Selector")
+
diff --git a/src/edje_externals/elm_fileselector_button.c b/src/edje_externals/elm_fileselector_button.c
new file mode 100644 (file)
index 0000000..6782b54
--- /dev/null
@@ -0,0 +1,252 @@
+#include "private.h"
+
+typedef struct _Elm_Params_fileselector_button
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+
+   struct {
+      const char *path;
+      Eina_Bool is_save:1;
+      Eina_Bool is_save_set:1;
+      Eina_Bool folder_only:1;
+      Eina_Bool folder_only_set:1;
+      Eina_Bool expandable:1;
+      Eina_Bool expandable_set:1;
+      Eina_Bool inwin_mode:1;
+      Eina_Bool inwin_mode_set:1;
+   } fs;
+} Elm_Params_fileselector_button;
+
+static void
+external_fileselector_button_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_fileselector_button *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_fileselector_button_label_set(obj, p->label);
+   if (p->icon) elm_fileselector_button_icon_set(obj, p->icon);
+   if (p->fs.path) elm_fileselector_button_path_set(obj, p->fs.path);
+   if (p->fs.is_save_set)
+     elm_fileselector_button_is_save_set(obj, p->fs.is_save);
+   if (p->fs.folder_only_set)
+     elm_fileselector_button_folder_only_set(obj, p->fs.folder_only);
+   if (p->fs.expandable_set)
+     elm_fileselector_button_expandable_set(obj, p->fs.expandable);
+   if (p->fs.inwin_mode_set)
+     elm_fileselector_button_inwin_mode_set(obj, p->fs.inwin_mode);
+}
+
+static Eina_Bool
+external_fileselector_button_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_fileselector_button_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_fileselector_button_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "path"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_fileselector_button_path_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "save"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_button_is_save_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "folder only"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_button_folder_only_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "expandable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_button_expandable_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inwin mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_button_inwin_mode_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_fileselector_button_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_fileselector_button_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "path"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_fileselector_button_path_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "save"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_button_is_save_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "folder only"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_button_folder_only_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "expandable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_button_expandable_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inwin mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_button_inwin_mode_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_fileselector_button_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_fileselector_button *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_fileselector_button));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "path"))
+         mem->fs.path = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "save"))
+         {
+            mem->fs.is_save = !!param->i;
+            mem->fs.is_save_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "folder only"))
+         {
+            mem->fs.folder_only = !!param->i;
+            mem->fs.folder_only_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "expandable"))
+         {
+            mem->fs.expandable = !!param->i;
+            mem->fs.expandable_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "inwin mode"))
+         {
+            mem->fs.inwin_mode = !!param->i;
+            mem->fs.inwin_mode_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "label"))
+         mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_fileselector_button_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+ static void
+external_fileselector_button_params_free(void *params)
+{
+   Elm_Params_fileselector_button *mem = params;
+
+   if (mem->fs.path)
+     eina_stringshare_del(mem->fs.path);
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_fileselector_button_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("path"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("save"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("folder only"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("expandable"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("inwin mode"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(fileselector_button, "fileselector_button");
+DEFINE_EXTERNAL_TYPE_SIMPLE(fileselector_button, "File Selector Button");
diff --git a/src/edje_externals/elm_fileselector_entry.c b/src/edje_externals/elm_fileselector_entry.c
new file mode 100644 (file)
index 0000000..2389b70
--- /dev/null
@@ -0,0 +1,252 @@
+#include "private.h"
+
+typedef struct _Elm_Params_fileselector_entry
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+
+   struct {
+      const char *path;
+      Eina_Bool is_save:1;
+      Eina_Bool is_save_set:1;
+      Eina_Bool folder_only:1;
+      Eina_Bool folder_only_set:1;
+      Eina_Bool expandable:1;
+      Eina_Bool expandable_set:1;
+      Eina_Bool inwin_mode:1;
+      Eina_Bool inwin_mode_set:1;
+   } fs;
+} Elm_Params_fileselector_entry;
+
+static void
+external_fileselector_entry_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_fileselector_entry *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_fileselector_entry_button_label_set(obj, p->label);
+   if (p->icon) elm_fileselector_entry_button_icon_set(obj, p->icon);
+   if (p->fs.path) elm_fileselector_entry_selected_set(obj, p->fs.path);
+   if (p->fs.is_save_set)
+     elm_fileselector_entry_is_save_set(obj, p->fs.is_save);
+   if (p->fs.folder_only_set)
+     elm_fileselector_entry_folder_only_set(obj, p->fs.folder_only);
+   if (p->fs.expandable_set)
+     elm_fileselector_entry_expandable_set(obj, p->fs.expandable);
+   if (p->fs.inwin_mode_set)
+     elm_fileselector_entry_inwin_mode_set(obj, p->fs.inwin_mode);
+}
+
+static Eina_Bool
+external_fileselector_entry_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_fileselector_entry_button_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_fileselector_entry_button_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "path"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_fileselector_entry_selected_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "save"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_entry_is_save_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "folder only"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_entry_folder_only_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "expandable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_entry_expandable_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inwin mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_fileselector_entry_inwin_mode_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_fileselector_entry_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_fileselector_entry_button_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "path"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_fileselector_entry_selected_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "save"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_entry_is_save_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "folder only"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_entry_folder_only_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "expandable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_entry_expandable_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inwin mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_fileselector_entry_inwin_mode_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_fileselector_entry_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_fileselector_entry *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_fileselector_entry));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "path"))
+         mem->fs.path = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "save"))
+         {
+            mem->fs.is_save = !!param->i;
+            mem->fs.is_save_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "folder only"))
+         {
+            mem->fs.folder_only = !!param->i;
+            mem->fs.folder_only_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "expandable"))
+         {
+            mem->fs.expandable = !!param->i;
+            mem->fs.expandable_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "inwin mode"))
+         {
+            mem->fs.inwin_mode = !!param->i;
+            mem->fs.inwin_mode_set = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "label"))
+         mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_fileselector_entry_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+ static void
+external_fileselector_entry_params_free(void *params)
+{
+   Elm_Params_fileselector_entry *mem = params;
+
+   if (mem->fs.path)
+     eina_stringshare_del(mem->fs.path);
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_fileselector_entry_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("path"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("save"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("folder only"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("expandable"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("inwin mode"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(fileselector_entry, "fileselector_entry");
+DEFINE_EXTERNAL_TYPE_SIMPLE(fileselector_entry, "File Selector Entry");
diff --git a/src/edje_externals/elm_genlist.c b/src/edje_externals/elm_genlist.c
new file mode 100644 (file)
index 0000000..41eaef8
--- /dev/null
@@ -0,0 +1,333 @@
+#include <assert.h>
+
+#include "private.h"
+
+typedef struct _Elm_Params_Genlist
+{
+   Elm_Params base;
+   const char *horizontal_mode;
+   Eina_Bool multi:1;
+   Eina_Bool multi_exists:1;
+   Eina_Bool always_select:1;
+   Eina_Bool always_select_exists:1;
+   Eina_Bool no_select:1;
+   Eina_Bool no_select_exists:1;
+   Eina_Bool compress:1;
+   Eina_Bool compress_exists:1;
+   Eina_Bool homogeneous:1;
+   Eina_Bool homogeneous_exists:1;
+   Eina_Bool h_bounce:1;
+   Eina_Bool h_bounce_exists:1;
+   Eina_Bool v_bounce:1;
+   Eina_Bool v_bounce_exists:1;
+} Elm_Params_Genlist;
+
+static const char* list_horizontal_mode_choices[] = {"compress", "scroll", "limit", "expand", NULL};
+
+static Elm_List_Mode
+_list_horizontal_mode_setting_get(const char *horizontal_mode_str)
+{
+   unsigned int i;
+
+   assert(sizeof(list_horizontal_mode_choices)/sizeof(list_horizontal_mode_choices[0]) == ELM_LIST_LAST + 1);
+
+   for (i = 0; i < sizeof(list_horizontal_mode_choices); i++)
+     {
+       if (!strcmp(horizontal_mode_str, list_horizontal_mode_choices[i]))
+         return i;
+     }
+   return ELM_LIST_LAST;
+}
+
+static void
+external_genlist_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Genlist *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->horizontal_mode)
+     {
+       Elm_List_Mode set = _list_horizontal_mode_setting_get(p->horizontal_mode);
+
+       if (set != ELM_LIST_LAST)
+          elm_genlist_horizontal_mode_set(obj, set);
+     }
+   if (p->multi_exists)
+     elm_genlist_multi_select_set(obj, p->multi);
+   if (p->always_select_exists)
+     elm_genlist_always_select_mode_set(obj, p->always_select);
+   if (p->no_select_exists)
+     elm_genlist_no_select_mode_set(obj, p->no_select);
+   if (p->compress_exists)
+     elm_genlist_compress_mode_set(obj, p->compress);
+   if (p->homogeneous_exists)
+     elm_genlist_homogeneous_set(obj, p->homogeneous);
+   if ((p->h_bounce_exists) && (p->v_bounce_exists))
+     elm_genlist_bounce_set(obj, p->h_bounce, p->v_bounce);
+   else if ((p->h_bounce_exists) || (p->v_bounce_exists))
+     {
+       Eina_Bool h_bounce, v_bounce;
+
+       elm_genlist_bounce_get(obj, &h_bounce, &v_bounce);
+       if (p->h_bounce_exists)
+         elm_genlist_bounce_set(obj, p->h_bounce, v_bounce);
+       else
+         elm_genlist_bounce_set(obj, h_bounce, p->v_bounce);
+     }
+}
+
+static Eina_Bool
+external_genlist_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "horizontal mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_List_Mode set = _list_horizontal_mode_setting_get(param->s);
+
+            if (set == ELM_LIST_LAST) return EINA_FALSE;
+            elm_genlist_horizontal_mode_set(obj, set);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "multi select"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_genlist_multi_select_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "always select"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_genlist_always_select_mode_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "no select"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_genlist_no_select_mode_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "compress"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_genlist_compress_mode_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "homogeneous"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_genlist_homogeneous_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "height bounce"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            Eina_Bool h_bounce, v_bounce;
+            elm_genlist_bounce_get(obj, &h_bounce, &v_bounce);
+            elm_genlist_bounce_set(obj, param->i, v_bounce);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "width bounce"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            Eina_Bool h_bounce, v_bounce;
+            elm_genlist_bounce_get(obj, &h_bounce, &v_bounce);
+            elm_genlist_bounce_set(obj, h_bounce, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_genlist_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "horizontal mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_List_Mode list_horizontal_mode_set = elm_genlist_horizontal_mode_get(obj);
+
+            if (list_horizontal_mode_set == ELM_LIST_LAST)
+              return EINA_FALSE;
+
+            param->s = list_horizontal_mode_choices[list_horizontal_mode_set];
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "multi select"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_genlist_multi_select_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "always select"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_genlist_always_select_mode_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "no select"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_genlist_no_select_mode_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "compress"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_genlist_compress_mode_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "homogeneous"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_genlist_homogeneous_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "height bounce"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            Eina_Bool h_bounce, v_bounce;
+            elm_genlist_bounce_get(obj, &h_bounce, &v_bounce);
+            param->i = h_bounce;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "width bounce"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            Eina_Bool h_bounce, v_bounce;
+            elm_genlist_bounce_get(obj, &h_bounce, &v_bounce);
+            param->i = v_bounce;
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_genlist_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Genlist *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = ELM_NEW(Elm_Params_Genlist);
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "horizontal mode"))
+            mem->horizontal_mode = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "multi select"))
+         {
+            mem->multi = !!param->i;
+            mem->multi_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "always select"))
+         {
+            mem->always_select = !!param->i;
+            mem->always_select_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "no select"))
+         {
+            mem->no_select = !!param->i;
+            mem->no_select_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "compress"))
+         {
+            mem->compress = !!param->i;
+            mem->compress_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "homogeneous"))
+         {
+            mem->homogeneous = !!param->i;
+            mem->homogeneous_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "height bounce"))
+         {
+            mem->h_bounce = !!param->i;
+            mem->h_bounce_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "width bounce"))
+         {
+            mem->v_bounce = !!param->i;
+            mem->v_bounce_exists = EINA_TRUE;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_genlist_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_genlist_params_free(void *params)
+{
+   Elm_Params_Genlist *mem = params;
+
+   if (mem->horizontal_mode)
+     eina_stringshare_del(mem->horizontal_mode);
+
+   free(mem);
+}
+
+static Edje_External_Param_Info external_genlist_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("horizontal mode", "scroll", list_horizontal_mode_choices),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("multi select"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("always select"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("no select"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("compress"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("homogeneous"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("height bounce"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("width bounce"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(genlist, "genlist");
+DEFINE_EXTERNAL_TYPE_SIMPLE(genlist, "Generic List");
diff --git a/src/edje_externals/elm_hoversel.c b/src/edje_externals/elm_hoversel.c
new file mode 100644 (file)
index 0000000..de4bbec
--- /dev/null
@@ -0,0 +1,148 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Hoversel
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+   Eina_Bool horizontal:1;
+   Eina_Bool horizontal_exists:1;
+} Elm_Params_Hoversel;
+
+static void
+external_hoversel_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Hoversel *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_hoversel_label_set(obj, p->label);
+   if (p->icon)
+     elm_hoversel_icon_set(obj, p->icon);
+   if (p->horizontal_exists)
+      elm_hoversel_horizontal_set(obj, p->horizontal);
+}
+
+static Eina_Bool
+external_hoversel_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_hoversel_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_hoversel_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "horizontal"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_hoversel_horizontal_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_hoversel_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_hoversel_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "horizontal"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_hoversel_horizontal_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_hoversel_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_Hoversel *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Hoversel));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "horizontal"))
+         {
+            mem->horizontal = !!param->i;
+            mem->horizontal_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "label"))
+         mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_hoversel_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+ static void
+external_hoversel_params_free(void *params)
+{
+   Elm_Params_Hoversel *mem = params;
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_hoversel_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("horizontal"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(hoversel, "hoversel");
+DEFINE_EXTERNAL_TYPE_SIMPLE(hoversel, "Hoversel");
diff --git a/src/edje_externals/elm_icon.c b/src/edje_externals/elm_icon.c
new file mode 100644 (file)
index 0000000..bce7a3e
--- /dev/null
@@ -0,0 +1,116 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Icon
+{
+   Elm_Params base;
+   const char *icon;
+} Elm_Params_Icon;
+
+static void
+external_icon_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Icon *p;
+   Evas_Object *edje;
+   const char *file;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->icon)
+   {
+          edje = evas_object_smart_parent_get(obj);
+          edje_object_file_get(edje, &file, NULL);
+
+          if (!elm_icon_file_set(obj, file, p->icon))
+                  elm_icon_standard_set(obj, p->icon);
+   }
+}
+
+static Eina_Bool
+external_icon_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   Evas_Object *edje;
+   const char *file;
+
+   if (!strcmp(param->name, "icon"))
+     {
+          if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+          {
+                  edje = evas_object_smart_parent_get(obj);
+                  edje_object_file_get(edje, &file, NULL);
+
+                  if (!elm_icon_file_set(obj, file, param->s))
+                          elm_icon_standard_set(obj, param->s);
+                  return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_icon_param_get(void *data __UNUSED__, const Evas_Object *obj __UNUSED__, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_icon_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Icon *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = ELM_NEW(Elm_Params_Icon);
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+   {
+          if (!strcmp(param->name, "icon"))
+          {
+                  mem->icon = eina_stringshare_add(param->s);
+          }
+   }
+
+   return mem;
+}
+
+static Evas_Object *external_icon_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("no content");
+       return NULL;
+}
+
+static void
+external_icon_params_free(void *params)
+{
+   Elm_Params_Icon *mem = params;
+
+   if (mem->icon)
+        eina_stringshare_del(mem->icon);
+   external_common_params_free(params);
+}
+
+static Edje_External_Param_Info external_icon_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(icon, "icon");
+DEFINE_EXTERNAL_TYPE_SIMPLE(icon, "Icon");
diff --git a/src/edje_externals/elm_label.c b/src/edje_externals/elm_label.c
new file mode 100644 (file)
index 0000000..09f8970
--- /dev/null
@@ -0,0 +1,87 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Label
+{
+   Elm_Params base;
+} Elm_Params_Label;
+
+static void
+external_label_state_set(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Label *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   //if (p->base.label) elm_label_label_set(obj, p->base.label);
+}
+
+static Eina_Bool
+external_label_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_label_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_label_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_label_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_label_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params __UNUSED__)
+{
+   Elm_Params_Label *mem;
+
+   mem = ELM_NEW(Elm_Params_Label);
+   if (!mem)
+     return NULL;
+
+   return mem;
+}
+
+static Evas_Object *external_label_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("no content");
+       return NULL;
+}
+
+static void
+external_label_params_free(void *params)
+{
+   external_common_params_free(params);
+}
+
+static Edje_External_Param_Info external_label_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(label, "label");
+DEFINE_EXTERNAL_TYPE_SIMPLE(label, "label");
diff --git a/src/edje_externals/elm_list.c b/src/edje_externals/elm_list.c
new file mode 100644 (file)
index 0000000..1d81349
--- /dev/null
@@ -0,0 +1,305 @@
+#include <assert.h>
+
+#include "private.h"
+
+typedef struct _Elm_Params_List
+{
+   Elm_Params base;
+   const char *policy_h;
+   const char *policy_v;
+   const char *mode;
+   Eina_Bool h_mode : 1;
+   Eina_Bool h_mode_exists : 1;
+   Eina_Bool multi : 1;
+   Eina_Bool multi_exists : 1;
+   Eina_Bool always_select : 1;
+   Eina_Bool always_select_exists : 1;
+} Elm_Params_List;
+
+#define CHOICE_GET(CHOICES, STR)                \
+  unsigned int i;                               \
+  for (i = 0; i < sizeof(CHOICES); i++)         \
+    if (strcmp(STR, CHOICES[i]) == 0)           \
+      return i
+
+static const char *scroller_policy_choices[] = {"auto", "on", "off", NULL};
+static const char *list_mode_choices[] = {"compress", "scroll", "limit",
+                                          "expand", NULL};
+
+static Elm_Scroller_Policy
+_scroller_policy_choices_setting_get(const char *policy_str)
+{
+   assert(sizeof(scroller_policy_choices)/
+          sizeof(scroller_policy_choices[0]) == ELM_SCROLLER_POLICY_LAST + 1);
+   CHOICE_GET(scroller_policy_choices, policy_str);
+   return ELM_SCROLLER_POLICY_LAST;
+}
+
+static Elm_List_Mode
+_list_mode_setting_get(const char *mode_str)
+{
+   assert(sizeof(list_mode_choices)/sizeof(list_mode_choices[0]) ==
+          ELM_LIST_LAST + 1);
+   CHOICE_GET(list_mode_choices, mode_str);
+   return ELM_LIST_LAST;
+}
+
+static void
+external_list_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_List *p;
+   Elm_Scroller_Policy policy_h, policy_v;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->mode)
+     {
+        Elm_List_Mode set = _list_mode_setting_get(p->mode);
+
+        if (set != ELM_LIST_LAST)
+          elm_list_mode_set(obj, set);
+     }
+
+   if ((p->policy_h) && (p->policy_v))
+     {
+        policy_h = _scroller_policy_choices_setting_get(p->policy_h);
+        policy_v = _scroller_policy_choices_setting_get(p->policy_v);
+        elm_list_scroller_policy_set(obj, policy_h, policy_v);
+     }
+   else if ((p->policy_h) || (p->policy_v))
+     {
+        elm_list_scroller_policy_get(obj, &policy_h, &policy_v);
+        if (p->policy_h)
+          {
+             policy_h = _scroller_policy_choices_setting_get(p->policy_h);
+             elm_list_scroller_policy_set(obj, policy_h, policy_v);
+          }
+        else
+          {
+             policy_v = _scroller_policy_choices_setting_get(p->policy_v);
+             elm_list_scroller_policy_set(obj, policy_h, policy_v);
+          }
+     }
+
+   if (p->h_mode_exists)
+     elm_list_horizontal_set(obj, p->h_mode);
+   if (p->multi_exists)
+     elm_list_multi_select_set(obj, p->multi);
+   if (p->always_select_exists)
+     elm_list_always_select_mode_set(obj, p->always_select);
+}
+
+static Eina_Bool
+external_list_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "list mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_List_Mode set = _list_mode_setting_get(param->s);
+             if (set == ELM_LIST_LAST) return EINA_FALSE;
+             elm_list_mode_set(obj, set);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "horizontal scroll"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_Scroller_Policy h, v;
+             elm_list_scroller_policy_get(obj, &h, &v);
+             h = _scroller_policy_choices_setting_get(param->s);
+             if (h == ELM_SCROLLER_POLICY_LAST) return EINA_FALSE;
+             elm_list_scroller_policy_set(obj, h, v);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "vertical scroll"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_Scroller_Policy h, v;
+             elm_list_scroller_policy_get(obj, &h, &v);
+             v = _scroller_policy_choices_setting_get(param->s);
+             if (v == ELM_SCROLLER_POLICY_LAST) return EINA_FALSE;
+             elm_list_scroller_policy_set(obj, h, v);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "horizontal mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             elm_list_horizontal_set(obj, param->i);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "multi-select mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             elm_list_multi_select_set(obj, param->i);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "always-select mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             elm_list_always_select_mode_set(obj, param->i);
+             return EINA_TRUE;
+          }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_list_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "horizontal mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             param->i = elm_list_horizontal_get(obj);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "multi-select mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             param->i = elm_list_multi_select_get(obj);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "always-select mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+          {
+             param->i = elm_list_always_select_mode_get(obj);
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "horizontal scroll"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_Scroller_Policy h, v;
+             elm_list_scroller_policy_get(obj, &h, &v);
+
+             param->s = scroller_policy_choices[h];
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "vertical scroll"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_Scroller_Policy h, v;
+             elm_list_scroller_policy_get(obj, &h, &v);
+
+             param->s = scroller_policy_choices[v];
+             return EINA_TRUE;
+          }
+     }
+   else if (!strcmp(param->name, "list mode"))
+     {
+        if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+          {
+             Elm_List_Mode m = elm_list_mode_get(obj);
+
+             if (m == ELM_LIST_LAST)
+               return EINA_FALSE;
+
+             param->s = list_mode_choices[m];
+             return EINA_TRUE;
+          }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_list_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_List *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = ELM_NEW(Elm_Params_List);
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+        if (!strcmp(param->name, "horizontal mode"))
+          {
+             mem->h_mode = param->i;
+             mem->h_mode_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "multi-select mode"))
+          {
+             mem->multi = param->i;
+             mem->multi_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "always-select mode"))
+          {
+             mem->always_select = param->i;
+             mem->always_select_exists = EINA_TRUE;
+          }
+        else if (!strcmp(param->name, "horizontal scroll"))
+          mem->policy_h = eina_stringshare_add(param->s);
+        else if (!strcmp(param->name, "vertical scroll"))
+          mem->policy_v = eina_stringshare_add(param->s);
+        else if (!strcmp(param->name, "list mode"))
+          mem->mode = eina_stringshare_add(param->s);
+     }
+   return mem;
+}
+
+static Evas_Object *external_list_content_get(void *data __UNUSED__, const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+   ERR("No content.");
+   return NULL;
+}
+
+static void
+external_list_params_free(void *params)
+{
+   Elm_Params_List *mem = params;
+
+   if (mem->mode)
+     eina_stringshare_del(mem->mode);
+   if (mem->policy_h)
+     eina_stringshare_del(mem->policy_h);
+   if (mem->policy_v)
+     eina_stringshare_del(mem->policy_v);
+
+   free(mem);
+}
+
+static Edje_External_Param_Info external_list_params[] = {
+  DEFINE_EXTERNAL_COMMON_PARAMS,
+  EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("list mode", "scroll",
+                                       list_mode_choices),
+  EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("horizontal scroll", "auto",
+                                       scroller_policy_choices),
+  EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("vertical scroll", "auto",
+                                       scroller_policy_choices),
+  EDJE_EXTERNAL_PARAM_INFO_BOOL("horizontal mode"),
+  EDJE_EXTERNAL_PARAM_INFO_BOOL("multi-select mode"),
+  EDJE_EXTERNAL_PARAM_INFO_BOOL("always-select mode"),
+  EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(list, "list")
+DEFINE_EXTERNAL_TYPE_SIMPLE(list, "List");
diff --git a/src/edje_externals/elm_map.c b/src/edje_externals/elm_map.c
new file mode 100644 (file)
index 0000000..c5e8386
--- /dev/null
@@ -0,0 +1,207 @@
+#include <assert.h>
+
+#include "private.h"
+
+typedef struct _Elm_Params_Map
+{
+   Elm_Params base;
+   const char *map_source;
+   const char *zoom_mode;
+   double zoom;
+   Eina_Bool zoom_set:1;
+} Elm_Params_Map;
+
+static const char *zoom_choices[] = {"manual", "auto fit", "auto fill", NULL};
+
+static const char *source_choices[] =
+  {"Mapnik", "Osmarender", "Cycle Map", "Maplint",
+   "Custom 1", "Custom 2", "Custom 3", "Custom 4",
+   "Custom 5", "Custom 6", "Custom 7"};
+
+static Elm_Map_Zoom_Mode
+_zoom_mode_get(const char *map_src)
+{
+   unsigned int i;
+
+   assert(sizeof(zoom_choices)/sizeof(zoom_choices[0]) ==
+         ELM_MAP_ZOOM_MODE_LAST + 1);
+
+   for (i = 0; i < sizeof(zoom_choices); i++)
+     if (!strcmp(map_src, zoom_choices[i])) return i;
+
+   return ELM_MAP_ZOOM_MODE_LAST;
+}
+
+static Elm_Map_Sources
+_map_source_get(const char *map_src)
+{
+   unsigned int i;
+
+   assert(sizeof(source_choices)/sizeof(source_choices[0]) ==
+         ELM_MAP_SOURCE_LAST);
+
+   for (i = 0; i < sizeof(source_choices); i++)
+     if (!strcmp(map_src, source_choices[i])) return i;
+
+   return ELM_MAP_SOURCE_LAST;
+}
+
+static void
+external_map_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Map *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->map_source)
+     {
+       Elm_Map_Sources set = _map_source_get(p->map_source);
+       if (set == ELM_MAP_SOURCE_LAST) return;
+       elm_map_source_set(obj, set);
+     }
+   if (p->zoom_mode)
+     {
+       Elm_Map_Zoom_Mode set = _zoom_mode_get(p->zoom_mode);
+       if (set == ELM_MAP_ZOOM_MODE_LAST) return;
+       elm_map_zoom_mode_set(obj, set);
+     }
+   if (p->zoom_set) elm_map_zoom_set(obj, p->zoom);
+}
+
+static Eina_Bool
+external_map_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "map source"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_Map_Sources set = _map_source_get(param->s);
+            if (set == ELM_MAP_SOURCE_LAST) return EINA_FALSE;
+            elm_map_source_set(obj, set);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_Map_Zoom_Mode set = _zoom_mode_get(param->s);
+            if (set == ELM_MAP_ZOOM_MODE_LAST) return EINA_FALSE;
+            elm_map_zoom_mode_set(obj, set);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom level"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            elm_map_zoom_set(obj, param->d);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_map_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "map source"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_Map_Sources set = elm_map_source_get(obj);
+            if (set == ELM_MAP_SOURCE_LAST) return EINA_FALSE;
+            param->s = source_choices[set];
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_Map_Zoom_Mode set = elm_map_zoom_mode_get(obj);
+            if (set == ELM_MAP_ZOOM_MODE_LAST) return EINA_FALSE;
+            param->s = zoom_choices[set];
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom level"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            param->d = elm_map_zoom_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_map_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Map *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Map));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "map source"))
+         mem->map_source = eina_stringshare_add(param->s);
+       if (!strcmp(param->name, "zoom mode"))
+         mem->zoom_mode = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "zoom level"))
+         {
+            mem->zoom = param->d;
+            mem->zoom_set = EINA_TRUE;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_map_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_map_params_free(void *params)
+{
+   Elm_Params_Map *mem = params;
+
+   if (mem->map_source)
+     eina_stringshare_del(mem->map_source);
+   if (mem->zoom_mode)
+     eina_stringshare_del(mem->zoom_mode);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_map_params[] =
+  {
+    DEFINE_EXTERNAL_COMMON_PARAMS,
+    EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("map source", "Mapnik",
+                                        source_choices),
+    EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("zoom mode", "manual", zoom_choices),
+    EDJE_EXTERNAL_PARAM_INFO_DOUBLE("zoom level"),
+    EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+  };
+
+DEFINE_EXTERNAL_ICON_ADD(map, "map")
+DEFINE_EXTERNAL_TYPE_SIMPLE(map, "Map")
+
diff --git a/src/edje_externals/elm_notify.c b/src/edje_externals/elm_notify.c
new file mode 100644 (file)
index 0000000..3eab33a
--- /dev/null
@@ -0,0 +1,199 @@
+#include "private.h"
+#include <assert.h>
+
+
+typedef struct _Elm_Params_Notify Elm_Params_Notify;
+
+struct _Elm_Params_Notify {
+       Elm_Params base;
+       Evas_Object *content; /* part name whose obj is to be set as content */
+       Eina_Bool repeat_events_exists;
+       Eina_Bool repeat_events;
+       Eina_Bool timeout_exists;
+       double timeout;
+
+       const char *orient;
+};
+
+
+static const char *orients[] = {
+               "top",
+               "center",
+               "bottom",
+               "left",
+               "right",
+               "top_left",
+               "top_right",
+               "bottom_left",
+               "bottom_right",
+               NULL
+};
+
+static Elm_Notify_Orient _orient_get(const char *orient)
+{
+   unsigned int i;
+
+   assert(sizeof(orients)/sizeof(orients[0]) ==
+         ELM_NOTIFY_ORIENT_LAST + 1);
+
+   for (i = 0; i < sizeof(orients); i++)
+     if (!strcmp(orient, orients[i])) return i;
+
+   return ELM_NOTIFY_ORIENT_LAST;
+}
+
+static void external_notify_state_set(void *data __UNUSED__,
+               Evas_Object *obj, const void *from_params,
+               const void *to_params, float pos __UNUSED__)
+{
+       const Elm_Params_Notify *p;
+
+       if (to_params) p = to_params;
+       else if (from_params) p = from_params;
+       else return;
+
+       if (p->content) {
+               elm_notify_content_set(obj, p->content);
+       }
+       if (p->repeat_events_exists)
+               elm_notify_repeat_events_set(obj, p->repeat_events);
+       if (p->timeout_exists)
+               elm_notify_timeout_set(obj, p->timeout);
+       if (p->orient)
+       {
+               Elm_Notify_Orient set = _orient_get(p->orient);
+               if (set == ELM_NOTIFY_ORIENT_LAST) return;
+               elm_notify_orient_set(obj, set);
+       }
+}
+
+static Eina_Bool external_notify_param_set(void *data __UNUSED__,
+               Evas_Object *obj, const Edje_External_Param *param)
+{
+       if ((!strcmp(param->name, "content"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING))
+       {
+               Evas_Object *content = external_common_param_edje_object_get(obj, param);
+               if ((strcmp(param->s, "")) && (!content))
+                       return EINA_FALSE;
+               elm_notify_content_set(obj, content);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "repeat_events"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL))
+       {
+               elm_notify_repeat_events_set(obj, param->i);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "timeout"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE))
+       {
+               elm_notify_timeout_set(obj, param->d);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "orient"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE))
+       {
+               Elm_Notify_Orient set = _orient_get(param->s);
+               if (set == ELM_NOTIFY_ORIENT_LAST) return EINA_FALSE;
+               elm_notify_orient_set(obj, set);
+               return EINA_TRUE;
+       }
+
+       ERR("unknown parameter '%s' of type '%s'",
+                       param->name, edje_external_param_type_str(param->type));
+
+       return EINA_FALSE;
+}
+
+static Eina_Bool external_notify_param_get(void *data __UNUSED__,
+               const Evas_Object *obj, Edje_External_Param *param)
+{
+       if (!strcmp(param->name, "content"))
+       {
+               /* not easy to get content name back from live object */
+               return EINA_FALSE;
+       }
+       else if ((!strcmp(param->name, "repeat_events"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL))
+       {
+               param->i = elm_notify_repeat_events_get(obj);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "timeout"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE))
+       {
+               param->d = elm_notify_timeout_get(obj);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "orient"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE))
+       {
+               Elm_Notify_Orient set = elm_notify_orient_get(obj);
+               if (set == ELM_NOTIFY_ORIENT_LAST) return EINA_FALSE;
+               param->s = orients[set];
+               return EINA_TRUE;
+       }
+
+       ERR("unknown parameter '%s' of type '%s'",
+                       param->name, edje_external_param_type_str(param->type));
+
+       return EINA_FALSE;
+}
+
+static void * external_notify_params_parse(void *data __UNUSED__, Evas_Object *obj,
+               const Eina_List *params) {
+       Elm_Params_Notify *mem;
+       Edje_External_Param *param;
+       const Eina_List *l;
+
+        mem = calloc(1, sizeof(Elm_Params_Notify));
+       if (!mem)
+               return NULL;
+
+       EINA_LIST_FOREACH(params, l, param)
+       {
+               if (!strcmp(param->name, "content"))
+                       mem->content = external_common_param_edje_object_get(obj, param);
+               else if (!strcmp(param->name, "timeout"))
+               {
+                       mem->timeout = param->d;
+                       mem->timeout_exists = EINA_TRUE;
+               }
+               else if (!strcmp(param->name, "repeat_events"))
+               {
+                       mem->repeat_events = param->i;
+                       mem->repeat_events_exists = EINA_TRUE;
+               }
+               else if (!strcmp(param->name, "orient"))
+                         mem->orient = eina_stringshare_add(param->s);
+       }
+
+       return mem;
+}
+
+static Evas_Object *external_notify_content_get(void *data __UNUSED__,
+               const Evas_Object *obj, const char *content)
+{
+       if (!strcmp(content, "content"))
+               return elm_notify_content_get(obj);
+
+       ERR("unknown content '%s'", content);
+       return NULL;
+}
+
+static void external_notify_params_free(void *params) {
+       free(params);
+}
+
+static Edje_External_Param_Info external_notify_params[] = {
+               DEFINE_EXTERNAL_COMMON_PARAMS,
+               EDJE_EXTERNAL_PARAM_INFO_STRING("content"),
+               EDJE_EXTERNAL_PARAM_INFO_BOOL("repeat_events"),
+               EDJE_EXTERNAL_PARAM_INFO_DOUBLE("timeout"),
+               EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(notify, "notify");
+DEFINE_EXTERNAL_TYPE_SIMPLE(notify, "Notify")
+;
diff --git a/src/edje_externals/elm_panes.c b/src/edje_externals/elm_panes.c
new file mode 100644 (file)
index 0000000..a965d31
--- /dev/null
@@ -0,0 +1,171 @@
+#include "private.h"
+#include <assert.h>
+
+
+typedef struct _Elm_Params_Panes Elm_Params_Panes;
+
+struct _Elm_Params_Panes {
+       Elm_Params base;
+       Evas_Object *content_left;
+       Evas_Object *content_right;
+       Eina_Bool is_horizontal;
+       Eina_Bool horizontal;
+       Eina_Bool is_left_size;
+       double left_size;
+};
+
+static void external_panes_state_set(void *data __UNUSED__,
+               Evas_Object *obj, const void *from_params,
+               const void *to_params, float pos __UNUSED__)
+{
+       const Elm_Params_Panes *p;
+
+       if (to_params) p = to_params;
+       else if (from_params) p = from_params;
+       else return;
+
+       if (p->content_left)
+               elm_panes_content_left_set(obj, p->content_left);
+
+       if (p->content_right)
+               elm_panes_content_right_set(obj, p->content_right);
+
+       if(p->is_left_size)
+               elm_panes_content_left_size_set(obj, p->left_size);
+
+       if(p->is_horizontal)
+               elm_panes_horizontal_set(obj, p->horizontal);
+}
+
+static Eina_Bool external_panes_param_set(void *data __UNUSED__,
+               Evas_Object *obj, const Edje_External_Param *param)
+{
+       if ((!strcmp(param->name, "content left"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING))
+       {
+               Evas_Object *content = external_common_param_edje_object_get(obj, param);
+               if ((strcmp(param->s, "")) && (!content))
+                       return EINA_FALSE;
+               elm_panes_content_left_set(obj, content);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "content right"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING))
+       {
+               Evas_Object *content = external_common_param_edje_object_get(obj, param);
+               if ((strcmp(param->s, "")) && (!content))
+                       return EINA_FALSE;
+               elm_panes_content_right_set(obj, content);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "horizontal"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL))
+       {
+               elm_panes_horizontal_set(obj, param->i);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "left size"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE))
+       {
+               elm_panes_content_left_size_set(obj, param->d);
+               return EINA_TRUE;
+       }
+
+       ERR("unknown parameter '%s' of type '%s'",
+                       param->name, edje_external_param_type_str(param->type));
+
+       return EINA_FALSE;
+}
+
+static Eina_Bool external_panes_param_get(void *data __UNUSED__,
+               const Evas_Object *obj, Edje_External_Param *param)
+{
+       if (!strcmp(param->name, "content left"))
+       {
+               /* not easy to get content name back from live object */
+               return EINA_FALSE;
+       }
+       else if (!strcmp(param->name, "content right"))
+       {
+               /* not easy to get content name back from live object */
+               return EINA_FALSE;
+       }
+       else if ((!strcmp(param->name, "horizontal"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL))
+       {
+               param->i = elm_panes_horizontal_get(obj);
+               return EINA_TRUE;
+       }
+       else if ((!strcmp(param->name, "left size"))
+                       && (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE))
+       {
+               param->d = elm_panes_content_left_size_get(obj);
+               return EINA_TRUE;
+       }
+
+       ERR("unknown parameter '%s' of type '%s'",
+                       param->name, edje_external_param_type_str(param->type));
+
+       return EINA_FALSE;
+}
+
+static void * external_panes_params_parse(void *data __UNUSED__, Evas_Object *obj,
+               const Eina_List *params) {
+       Elm_Params_Panes *mem;
+       Edje_External_Param *param;
+       const Eina_List *l;
+
+        mem = calloc(1, sizeof(Elm_Params_Panes));
+       if (!mem)
+               return NULL;
+
+       EINA_LIST_FOREACH(params, l, param)
+       {
+               if (!strcmp(param->name, "content left"))
+                       mem->content_left = external_common_param_edje_object_get(obj, param);
+               else if (!strcmp(param->name, "content right"))
+                               mem->content_right = external_common_param_edje_object_get(obj, param);
+               else if (!strcmp(param->name, "horizontal"))
+               {
+                       mem->is_horizontal = EINA_TRUE;
+                       mem->horizontal = param->i;
+               }
+               else if (!strcmp(param->name, "left size"))
+               {
+                       mem->is_left_size = EINA_TRUE;
+                       mem->left_size = param->d;
+               }
+       }
+
+       return mem;
+}
+
+static Evas_Object *external_panes_content_get(void *data __UNUSED__,
+               const Evas_Object *obj, const char *content)
+{
+       if (!strcmp(content, "left"))
+               return elm_panes_content_left_get(obj);
+       else if (!strcmp(content, "right"))
+               return elm_panes_content_right_get(obj);
+
+       ERR("unknown content '%s'", content);
+
+       return NULL;
+}
+
+
+static void external_panes_params_free(void *params) {
+       free(params);
+}
+
+static Edje_External_Param_Info external_panes_params[] = {
+               DEFINE_EXTERNAL_COMMON_PARAMS,
+               EDJE_EXTERNAL_PARAM_INFO_STRING("content left"),
+               EDJE_EXTERNAL_PARAM_INFO_STRING("content right"),
+               EDJE_EXTERNAL_PARAM_INFO_BOOL("horizontal"),
+               EDJE_EXTERNAL_PARAM_INFO_DOUBLE("left size"),
+               EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(panes, "panes");
+DEFINE_EXTERNAL_TYPE_SIMPLE(panes, "panes");
diff --git a/src/edje_externals/elm_photocam.c b/src/edje_externals/elm_photocam.c
new file mode 100644 (file)
index 0000000..a38e708
--- /dev/null
@@ -0,0 +1,208 @@
+#include <assert.h>
+
+#include "private.h"
+
+typedef struct _Elm_Params_Photocam
+{
+   Elm_Params base;
+   const char *file;
+   double zoom;
+   const char *zoom_mode;
+   Eina_Bool paused:1;
+   Eina_Bool paused_exists:1;
+   Eina_Bool zoom_exists:1;
+} Elm_Params_Photocam;
+
+static const char* choices[] = {"manual", "auto fit", "auto fill", NULL};
+
+static Elm_Photocam_Zoom_Mode
+_zoom_mode_setting_get(const char *zoom_mode_str)
+{
+   unsigned int i;
+
+   assert(sizeof(choices)/sizeof(choices[0]) == ELM_PHOTOCAM_ZOOM_MODE_LAST + 1);
+
+   for (i = 0; i < sizeof(choices); i++)
+     {
+       if (!strcmp(zoom_mode_str, choices[i]))
+         return i;
+     }
+   return ELM_PHOTOCAM_ZOOM_MODE_LAST;
+}
+
+static void
+external_photocam_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Photocam *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->file)
+     elm_photocam_file_set(obj, p->file);
+   if (p->zoom_exists)
+     elm_photocam_zoom_set(obj, p->zoom);
+   if (p->zoom_mode)
+     {
+       Elm_Photocam_Zoom_Mode set = _zoom_mode_setting_get(p->zoom_mode);
+       if (set == ELM_PHOTOCAM_ZOOM_MODE_LAST) return;
+       elm_photocam_zoom_mode_set(obj, set);
+     }
+   if (p->paused_exists)
+     elm_photocam_paused_set(obj, p->paused);
+}
+
+static Eina_Bool
+external_photocam_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "file"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_photocam_file_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            elm_photocam_zoom_set(obj, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Elm_Photocam_Zoom_Mode set = _zoom_mode_setting_get(param->s);
+            if (set == ELM_PHOTOCAM_ZOOM_MODE_LAST) return EINA_FALSE;
+            elm_photocam_zoom_mode_set(obj, set);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "paused"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_photocam_paused_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_photocam_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "file"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_photocam_file_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            param->d = elm_photocam_zoom_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "zoom mode"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Elm_Photocam_Zoom_Mode zoom_mode_set = elm_photocam_zoom_mode_get(obj);
+
+            if (zoom_mode_set == ELM_PHOTOCAM_ZOOM_MODE_LAST)
+              return EINA_FALSE;
+
+            param->s = choices[zoom_mode_set];
+            return EINA_TRUE;
+         }
+     }
+   else if(!strcmp(param->name, "paused"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_photocam_paused_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_photocam_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Photocam *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Photocam));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "file"))
+         mem->file = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "zoom"))
+         {
+            mem->zoom = param->d;
+            mem->zoom_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "zoom mode"))
+         mem->zoom_mode = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "paused"))
+         {
+            mem->paused = !!param->i;
+            mem->paused_exists = EINA_TRUE;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_photocam_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_photocam_params_free(void *params)
+{
+   Elm_Params_Photocam *mem = params;
+
+   if (mem->file)
+     eina_stringshare_del(mem->file);
+   if (mem->zoom_mode)
+     eina_stringshare_del(mem->zoom_mode);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_photocam_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("file"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("zoom"),
+   EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("zoom mode", "manual", choices),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("paused"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(photocam, "photocam");
+DEFINE_EXTERNAL_TYPE_SIMPLE(photocam, "Photocam");
diff --git a/src/edje_externals/elm_progressbar.c b/src/edje_externals/elm_progressbar.c
new file mode 100644 (file)
index 0000000..d7bdee3
--- /dev/null
@@ -0,0 +1,251 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Progressbar
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+   const char *unit;
+   double value;
+   Evas_Coord span;
+   Eina_Bool value_exists:1;
+   Eina_Bool span_exists:1;
+   Eina_Bool inverted:1;
+   Eina_Bool inverted_exists:1;
+   Eina_Bool horizontal:1;
+   Eina_Bool horizontal_exists:1;
+} Elm_Params_Progressbar;
+
+static void
+external_progressbar_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Progressbar *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_progressbar_label_set(obj, p->label);
+   if (p->icon)
+     elm_progressbar_icon_set(obj, p->icon);
+   if (p->span_exists)
+     elm_progressbar_span_size_set(obj, p->span);
+   if (p->value_exists)
+     elm_progressbar_value_set(obj, p->value);
+   if (p->inverted_exists)
+     elm_progressbar_inverted_set(obj, p->inverted);
+   if (p->horizontal_exists)
+     elm_progressbar_horizontal_set(obj, p->horizontal);
+   if (p->unit)
+     elm_progressbar_unit_format_set(obj, p->unit);
+}
+
+static Eina_Bool
+external_progressbar_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_progressbar_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_progressbar_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            elm_progressbar_value_set(obj, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "horizontal"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_progressbar_horizontal_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inverted"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_progressbar_inverted_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "span"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            elm_progressbar_span_size_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "unit format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_progressbar_unit_format_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_progressbar_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_progressbar_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            param->d = elm_progressbar_value_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "horizontal"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_progressbar_horizontal_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inverted"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_progressbar_inverted_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "span"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            param->i = elm_progressbar_span_size_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "unit format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_progressbar_unit_format_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_progressbar_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Progressbar *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Progressbar));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "span"))
+         {
+            mem->span = param->i;
+            mem->span_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "value"))
+         {
+            mem->value = param->d;
+            mem->value_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "inverted"))
+         {
+            mem->inverted = !!param->i;
+            mem->inverted_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "horizontal"))
+         {
+             mem->horizontal = !!param->i;
+             mem->horizontal_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "unit format"))
+         mem->unit = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "label"))
+         mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_progressbar_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_progressbar_params_free(void *params)
+{
+   Elm_Params_Progressbar *mem = params;
+
+   if (mem->unit)
+     eina_stringshare_del(mem->unit);
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_progressbar_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("value"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("horizontal"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("inverted"),
+   EDJE_EXTERNAL_PARAM_INFO_INT("span"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("unit format", "%1.2f"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(progressbar, "progressbar")
+DEFINE_EXTERNAL_TYPE_SIMPLE(progressbar, "Progressbar")
diff --git a/src/edje_externals/elm_radio.c b/src/edje_externals/elm_radio.c
new file mode 100644 (file)
index 0000000..1345122
--- /dev/null
@@ -0,0 +1,176 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Radio
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+   const char* group_name;
+   int value;
+   Eina_Bool value_exists:1;
+} Elm_Params_Radio;
+
+static void
+external_radio_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Radio *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_radio_label_set(obj, p->label);
+   if (p->icon)
+     elm_radio_icon_set(obj, p->icon);
+   if (p->value_exists)
+     elm_radio_state_value_set(obj, p->value);
+   if (p->group_name)
+     {
+       Evas_Object *ed = evas_object_smart_parent_get(obj);
+       Evas_Object *group = edje_object_part_swallow_get(ed, p->group_name);
+       elm_radio_group_add(obj, group);
+     }
+}
+
+static Eina_Bool
+external_radio_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_radio_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_radio_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            elm_radio_value_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "group"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *ed = evas_object_smart_parent_get(obj);
+            Evas_Object *group = edje_object_part_swallow_get(ed, param->s);
+            elm_radio_group_add(obj, group);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_radio_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_radio_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            param->i = elm_radio_value_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "group"))
+     {
+       /* not easy to get group name back from live object */
+       return EINA_FALSE;
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_radio_params_parse(void *data __UNUSED__, Evas_Object *obj, const Eina_List *params)
+{
+   Elm_Params_Radio *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Radio));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "group"))
+         mem->group_name = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "value"))
+         {
+            mem->value = param->i;
+            mem->value_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "label"))
+         mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_radio_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_radio_params_free(void *params)
+{
+   Elm_Params_Radio *mem = params;
+
+   if (mem->group_name)
+     eina_stringshare_del(mem->group_name);
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_radio_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("group"),
+   EDJE_EXTERNAL_PARAM_INFO_INT("value"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(radio, "radio")
+DEFINE_EXTERNAL_TYPE_SIMPLE(radio, "Radio")
diff --git a/src/edje_externals/elm_scrolled_entry.c b/src/edje_externals/elm_scrolled_entry.c
new file mode 100644 (file)
index 0000000..266e0e1
--- /dev/null
@@ -0,0 +1,184 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Entry
+{
+   Elm_Params base;
+   const char *text;
+   Eina_Bool text_set:1;
+   Eina_Bool editable:1;
+   Eina_Bool single:1;
+   Eina_Bool password:1;
+   Eina_Bool editable_exists:1;
+   Eina_Bool single_exists:1;
+   Eina_Bool password_exists:1;
+} Elm_Params_Entry;
+
+static void
+external_scrolled_entry_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Entry *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if ((!p->text_set) && (p->text))
+     {
+       elm_scrolled_entry_entry_set(obj, p->text);
+       ((Elm_Params_Entry *)p)->text_set = EINA_TRUE;
+     }
+   if (p->editable_exists)
+     elm_scrolled_entry_editable_set(obj, p->editable);
+   if (p->single_exists)
+     elm_scrolled_entry_single_line_set(obj, p->single);
+   if (p->password_exists)
+     elm_scrolled_entry_password_set(obj, p->password);
+}
+
+static Eina_Bool
+external_scrolled_entry_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "text"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_scrolled_entry_entry_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "editable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_scrolled_entry_editable_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "single line"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_scrolled_entry_single_line_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "password"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_scrolled_entry_password_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_scrolled_entry_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "text"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_scrolled_entry_entry_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "editable"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_scrolled_entry_editable_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "single line"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_scrolled_entry_single_line_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "password"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_scrolled_entry_password_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_scrolled_entry_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Entry *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Entry));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "text"))
+         mem->text = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "single line"))
+         {
+            mem->single = !!param->i;
+            mem->single_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "password"))
+         {
+            mem->password = !!param->i;
+            mem->password_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "editable"))
+         {
+            mem->editable = param->i;
+            mem->editable_exists = EINA_TRUE;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_scrolled_entry_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_scrolled_entry_params_free(void *params)
+{
+   Elm_Params_Entry *mem = params;
+
+   if (mem->text)
+     eina_stringshare_del(mem->text);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_scrolled_entry_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("text", "some text"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("editable"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("single line"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("password"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(scrolled_entry, "scrolled_entry")
+DEFINE_EXTERNAL_TYPE_SIMPLE(scrolled_entry, "Entry");
diff --git a/src/edje_externals/elm_scroller.c b/src/edje_externals/elm_scroller.c
new file mode 100644 (file)
index 0000000..ccec362
--- /dev/null
@@ -0,0 +1,104 @@
+#include "private.h"
+#include <assert.h>
+
+
+typedef struct _Elm_Params_Scroller Elm_Params_Scroller;
+
+struct _Elm_Params_Scroller {
+       Elm_Params base;
+       Evas_Object *content;
+};
+
+
+
+static void external_scroller_state_set(void *data __UNUSED__,
+               Evas_Object *obj, const void *from_params,
+               const void *to_params, float pos __UNUSED__)
+{
+       const Elm_Params_Scroller *p;
+
+       if (to_params) p = to_params;
+       else if (from_params) p = from_params;
+       else return;
+
+       if (p->content) {
+               elm_scroller_content_set(obj, p->content);
+       }
+}
+
+static Eina_Bool external_scroller_param_set(void *data __UNUSED__,
+               Evas_Object *obj, const Edje_External_Param *param)
+{
+       if (!strcmp(param->name, "content")
+                       && param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+       {
+               Evas_Object *content = external_common_param_edje_object_get(obj, param);
+               if ((strcmp(param->s, "")) && (!content))
+                       return EINA_FALSE;
+               elm_scroller_content_set(obj, content);
+               return EINA_TRUE;
+       }
+
+       ERR("unknown parameter '%s' of type '%s'",
+                       param->name, edje_external_param_type_str(param->type));
+
+       return EINA_FALSE;
+}
+
+static Eina_Bool external_scroller_param_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, Edje_External_Param *param)
+{
+       if (!strcmp(param->name, "content"))
+       {
+               /* not easy to get content name back from live object */
+               return EINA_FALSE;
+       }
+
+       ERR("unknown parameter '%s' of type '%s'",
+                       param->name, edje_external_param_type_str(param->type));
+
+       return EINA_FALSE;
+}
+
+static void * external_scroller_params_parse(void *data __UNUSED__, Evas_Object *obj,
+               const Eina_List *params) {
+       Elm_Params_Scroller *mem;
+       Edje_External_Param *param;
+       const Eina_List *l;
+
+        mem = ELM_NEW(Elm_Params_Scroller);
+       if (!mem)
+               return NULL;
+
+       EINA_LIST_FOREACH(params, l, param)
+       {
+               if (!strcmp(param->name, "content"))
+                       mem->content = external_common_param_edje_object_get(obj, param);
+       }
+
+       return mem;
+}
+
+static Evas_Object *external_scroller_content_get(void *data __UNUSED__,
+               const Evas_Object *obj, const char *content)
+{
+       if (!strcmp(content, "content"))
+               return elm_scroller_content_get(obj);
+
+       ERR("unknown content '%s'", content);
+       return NULL;
+}
+
+static void external_scroller_params_free(void *params) {
+       external_common_params_free(params);
+}
+
+static Edje_External_Param_Info external_scroller_params[] = {
+               DEFINE_EXTERNAL_COMMON_PARAMS,
+               EDJE_EXTERNAL_PARAM_INFO_STRING("content"),
+               EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(scroller, "scroller");
+DEFINE_EXTERNAL_TYPE_SIMPLE(scroller, "Scroller")
+;
diff --git a/src/edje_externals/elm_slider.c b/src/edje_externals/elm_slider.c
new file mode 100644 (file)
index 0000000..b559400
--- /dev/null
@@ -0,0 +1,339 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Slider
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+   const char *indicator, *unit;
+   double min, max, value;
+   Eina_Bool min_exists:1;
+   Eina_Bool max_exists:1;
+   Eina_Bool value_exists:1;
+   Eina_Bool inverted:1;
+   Eina_Bool inverted_exists:1;
+   Eina_Bool span:1;
+   Eina_Bool span_exists:1;
+   Eina_Bool horizontal:1;
+   Eina_Bool horizontal_exists:1;
+} Elm_Params_Slider;
+
+static void
+external_slider_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Slider *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_slider_label_set(obj, p->label);
+   if (p->icon)
+     elm_slider_icon_set(obj, p->icon);
+   if (p->span_exists)
+     elm_slider_span_size_set(obj, p->span);
+   if ((p->min_exists) && (p->max_exists))
+     elm_slider_min_max_set(obj, p->min, p->max);
+   else if ((p->min_exists) || (p->max_exists))
+     {
+       double min, max;
+       elm_slider_min_max_get(obj, &min, &max);
+       if (p->min_exists)
+         elm_slider_min_max_set(obj, p->min, max);
+       else
+         elm_slider_min_max_set(obj, min, p->max);
+     }
+   if (p->value_exists)
+     elm_slider_value_set(obj, p->value);
+   if (p->inverted_exists)
+     elm_slider_inverted_set(obj, p->inverted);
+   if (p->horizontal_exists)
+     elm_slider_horizontal_set(obj, p->horizontal);
+   if (p->indicator)
+     elm_slider_indicator_format_set(obj, p->indicator);
+   if (p->unit)
+     elm_slider_unit_format_set(obj, p->unit);
+}
+
+static Eina_Bool
+external_slider_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_slider_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_slider_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "min"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            double min, max;
+            elm_slider_min_max_get(obj, &min, &max);
+            elm_slider_min_max_set(obj, param->d, max);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "max"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            double min, max;
+            elm_slider_min_max_get(obj, &min, &max);
+            elm_slider_min_max_set(obj, min, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            elm_slider_value_set(obj, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "horizontal"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_slider_horizontal_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inverted"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_slider_inverted_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "span"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            elm_slider_span_size_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "unit format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_slider_unit_format_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "indicator format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_slider_indicator_format_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_slider_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_slider_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "min"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            double min, max;
+            elm_slider_min_max_get(obj, &min, &max);
+            param->d = min;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "max"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            double min, max;
+            elm_slider_min_max_get(obj, &min, &max);
+            param->d = max;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            param->d = elm_slider_value_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "horizontal"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_slider_horizontal_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "inverted"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_slider_inverted_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "span"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            param->i = elm_slider_span_size_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "unit format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_slider_unit_format_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "indicator format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_slider_indicator_format_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_slider_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Slider *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Slider));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "span"))
+         {
+            mem->span = param->i;
+            mem->span_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "min"))
+         {
+            mem->min = param->d;
+            mem->min_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "max"))
+         {
+            mem->max = param->d;
+            mem->max_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "value"))
+         {
+            mem->value = param->d;
+            mem->value_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "inverted"))
+         {
+            mem->inverted = param->i;
+            mem->inverted_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "horizontal"))
+         {
+            mem->horizontal = param->i;
+            mem->horizontal_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "unit format"))
+         mem->unit = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "indicator format"))
+         mem->indicator = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "label"))
+         mem->label = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_slider_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_slider_params_free(void *params)
+{
+   Elm_Params_Slider *mem = params;
+
+   if (mem->unit)
+     eina_stringshare_del(mem->unit);
+   if (mem->indicator)
+     eina_stringshare_del(mem->indicator);
+   if (mem->label)
+     eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_slider_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("min"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("max", 10.0),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("value"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("horizontal"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("inverted"),
+   EDJE_EXTERNAL_PARAM_INFO_INT("span"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("unit format", "%1.2f"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("indicator format", "%1.2f"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(slider, "slider")
+DEFINE_EXTERNAL_TYPE_SIMPLE(slider, "Slider")
diff --git a/src/edje_externals/elm_slideshow.c b/src/edje_externals/elm_slideshow.c
new file mode 100644 (file)
index 0000000..913dfaa
--- /dev/null
@@ -0,0 +1,182 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Slideshow
+{
+   Elm_Params base;
+   int timeout;
+   const char *transition;
+   const char *layout;
+   Eina_Bool loop:1;
+   Eina_Bool timeout_exists:1;
+   Eina_Bool loop_exists:1;
+} Elm_Params_Slideshow;
+
+static const char *transitions[] = { "fade", "black_fade", "horizontal",
+                                    "vertical", "square", NULL};
+static const char *layout[] = { "fullscreen", "not_fullscreen", NULL};
+
+static void
+external_slideshow_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Slideshow *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->timeout_exists)
+     elm_slideshow_timeout_set(obj , p->timeout);
+   if (p->loop_exists)
+     elm_slideshow_loop_set(obj, p->loop);
+   if (p->transition) {
+      elm_slideshow_transition_set(obj, p->transition);
+   }
+   if (p->layout) {
+         elm_slideshow_layout_set(obj, p->layout);
+   }
+}
+
+static Eina_Bool
+external_slideshow_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "timeout"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            elm_slideshow_timeout_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "loop"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_slideshow_loop_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "transition"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_slideshow_transition_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "layout"))
+        {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_slideshow_layout_set(obj, param->s);
+            return EINA_TRUE;
+         }
+        }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_slideshow_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "timeout"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            param->i = elm_slideshow_timeout_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "loop"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_slideshow_loop_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "transition"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_slideshow_transition_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "layout"))
+        {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_slideshow_layout_get(obj);
+            return EINA_TRUE;
+         }
+        }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_slideshow_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Slideshow *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Slideshow));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "timeout"))
+         {
+            mem->timeout = param->i;
+            mem->timeout_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "loop"))
+         {
+            mem->loop = param->i;
+            mem->loop_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "transition"))
+         {
+            mem->transition = param->s;
+         }
+    else if (!strcmp(param->name, "layout"))
+         {
+            mem->layout = param->s;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_slideshow_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_slideshow_params_free(void *params __UNUSED__)
+{
+   return;
+}
+
+static Edje_External_Param_Info external_slideshow_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_INT("timeout"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("loop"),
+   EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("transition", "fade", transitions),
+   EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("layout", "fullscreen", layout),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(slideshow, "slideshow");
+DEFINE_EXTERNAL_TYPE_SIMPLE(slideshow, "Slideshow");
diff --git a/src/edje_externals/elm_spinner.c b/src/edje_externals/elm_spinner.c
new file mode 100644 (file)
index 0000000..8978cb6
--- /dev/null
@@ -0,0 +1,244 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Spinner
+{
+   Elm_Params base;
+   const char *label_format;
+   double min, max, step, value;
+   Eina_Bool min_exists:1;
+   Eina_Bool max_exists:1;
+   Eina_Bool step_exists:1;
+   Eina_Bool value_exists:1;
+   Eina_Bool wrap_exists:1;
+   Eina_Bool wrap:1;
+} Elm_Params_Spinner;
+
+static void
+external_spinner_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Spinner *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label_format)
+     elm_spinner_label_format_set(obj, p->label_format);
+   if ((p->min_exists) && (p->max_exists))
+     elm_spinner_min_max_set(obj, p->min, p->max);
+   else if ((p->min_exists) || (p->max_exists))
+     {
+       double min, max;
+       elm_spinner_min_max_get(obj, &min, &max);
+       if (p->min_exists)
+         elm_spinner_min_max_set(obj, p->min, max);
+       else
+         elm_spinner_min_max_set(obj, min, p->max);
+     }
+   if (p->step_exists)
+     elm_spinner_step_set(obj, p->step);
+   if (p->value_exists)
+     elm_spinner_value_set(obj, p->value);
+   if (p->wrap_exists)
+     elm_spinner_wrap_set(obj, p->wrap);
+}
+
+static Eina_Bool
+external_spinner_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_spinner_label_format_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "min"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            double min, max;
+            elm_spinner_min_max_get(obj, &min, &max);
+            elm_spinner_min_max_set(obj, param->d, max);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "max"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            double min, max;
+            elm_spinner_min_max_get(obj, &min, &max);
+            elm_spinner_min_max_set(obj, min, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "step"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            elm_spinner_step_set(obj, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            elm_spinner_value_set(obj, param->d);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "wrap"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_spinner_wrap_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_spinner_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label format"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_spinner_label_format_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "min"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            double min, max;
+            elm_spinner_min_max_get(obj, &min, &max);
+            param->d = min;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "max"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            double min, max;
+            elm_spinner_min_max_get(obj, &min, &max);
+            param->d = max;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "step"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            param->d = elm_spinner_step_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "value"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            param->d = elm_spinner_value_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "wrap"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_spinner_value_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_spinner_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Spinner *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Spinner));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "label format"))
+         mem->label_format = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "min"))
+         {
+            mem->min = param->d;
+            mem->min_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "max"))
+         {
+            mem->max = param->d;
+            mem->max_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "step"))
+         {
+            mem->step = param->d;
+            mem->step_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "value"))
+         {
+            mem->value = param->d;
+            mem->value_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "wrap"))
+         {
+            mem->wrap = param->i;
+            mem->wrap_exists = EINA_TRUE;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_spinner_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_spinner_params_free(void *params)
+{
+   Elm_Params_Spinner *mem = params;
+
+   if (mem->label_format)
+     eina_stringshare_del(mem->label_format);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_spinner_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("label format", "%1.2f"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("min"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("max", 100.0),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("step", 1.0),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("value"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("wrap"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(spinner, "spinner")
+DEFINE_EXTERNAL_TYPE_SIMPLE(spinner, "Spinner")
diff --git a/src/edje_externals/elm_thumb.c b/src/edje_externals/elm_thumb.c
new file mode 100644 (file)
index 0000000..412cd04
--- /dev/null
@@ -0,0 +1,146 @@
+#include <assert.h>
+
+#include "private.h"
+
+typedef struct _Elm_Params_Thumb
+{
+   Elm_Params base;
+   const char *animate;
+} Elm_Params_Thumb;
+
+static const char* choices[] = {"loop", "start", "stop", NULL};
+
+static Elm_Thumb_Animation_Setting
+_anim_setting_get(const char *anim_str)
+{
+   unsigned int i;
+
+   assert(sizeof(choices)/sizeof(choices[0]) == ELM_THUMB_ANIMATION_LAST + 1);
+
+   for (i = 0; i < sizeof(choices); i++)
+     {
+       if (!strcmp(anim_str, choices[i]))
+         return i;
+     }
+   return ELM_THUMB_ANIMATION_LAST;
+}
+
+static void
+external_thumb_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Thumb *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->animate)
+     {
+       Elm_Thumb_Animation_Setting set = _anim_setting_get(p->animate);
+       if (set != ELM_THUMB_ANIMATION_LAST)
+          elm_thumb_animate_set(obj, set);
+     }
+}
+
+static Eina_Bool
+external_thumb_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "animate"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_Thumb_Animation_Setting set = _anim_setting_get(param->s);
+            if (set == ELM_THUMB_ANIMATION_LAST) return EINA_FALSE;
+            elm_thumb_animate_set(obj, set);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_thumb_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "animate"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+         {
+            Elm_Thumb_Animation_Setting anim_set = elm_thumb_animate_get(obj);
+
+            if (anim_set == ELM_THUMB_ANIMATION_LAST)
+              return EINA_FALSE;
+
+            param->s = choices[anim_set];
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_thumb_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Thumb *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Thumb));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "animate"))
+         mem->animate = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_thumb_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_thumb_params_free(void *params)
+{
+   Elm_Params_Thumb *mem = params;
+
+   if (mem->animate)
+     eina_stringshare_del(mem->animate);
+   free(mem);
+}
+
+static Edje_External_Param_Info external_thumb_params[] =
+  {
+    DEFINE_EXTERNAL_COMMON_PARAMS,
+    EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("animate", "loop", choices),
+    EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+  };
+
+DEFINE_EXTERNAL_ICON_ADD(thumb, "thumb")
+
+static Evas_Object *
+external_thumb_add(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *edje, const Eina_List *params __UNUSED__, const char *part_name)
+{
+   Evas_Object *parent, *obj;
+   external_elm_init();
+   parent = elm_widget_parent_widget_get(edje);
+   if (!parent) parent = edje;
+   elm_need_ethumb(); /* extra command needed */
+   obj = elm_thumb_add(parent);
+   external_signals_proxy(obj, edje, part_name);
+   return obj;
+}
+DEFINE_EXTERNAL_TYPE(thumb, "Thumbnail")
diff --git a/src/edje_externals/elm_toggle.c b/src/edje_externals/elm_toggle.c
new file mode 100644 (file)
index 0000000..5b28058
--- /dev/null
@@ -0,0 +1,212 @@
+#include <string.h>
+
+#include "private.h"
+
+typedef struct _Elm_Params_Toggle
+{
+   Elm_Params base;
+   const char *label;
+   Evas_Object *icon;
+   const char *on, *off;
+   Eina_Bool state:1;
+   Eina_Bool state_exists:1;
+} Elm_Params_Toggle;
+
+static void
+external_toggle_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Toggle *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->label)
+     elm_toggle_label_set(obj, p->label);
+   if (p->icon)
+     elm_toggle_icon_set(obj, p->icon);
+
+   if ((p->on) && (p->off))
+     elm_toggle_states_labels_set(obj, p->on, p->off);
+   else if ((p->on) || (p->off))
+     {
+       const char *on, *off;
+       elm_toggle_states_labels_get(obj, &on, &off);
+       if (p->on)
+         elm_toggle_states_labels_set(obj, p->on, off);
+       else
+         elm_toggle_states_labels_set(obj, on, p->off);
+     }
+
+   if (p->state_exists)
+     elm_toggle_state_set(obj, p->state);
+}
+
+static Eina_Bool
+external_toggle_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            elm_toggle_label_set(obj, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            Evas_Object *icon = external_common_param_icon_get(obj, param);
+            if ((strcmp(param->s, "")) && (!icon)) return EINA_FALSE;
+            elm_toggle_icon_set(obj, icon);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "label on"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            const char *on, *off;
+            elm_toggle_states_labels_get(obj, &on, &off);
+            elm_toggle_states_labels_set(obj, param->s, off);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "label off"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            const char *on, *off;
+            elm_toggle_states_labels_get(obj, &on, &off);
+            elm_toggle_states_labels_set(obj, on, param->s);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "state"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            elm_toggle_state_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_toggle_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "label"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            param->s = elm_toggle_label_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "icon"))
+     {
+       /* not easy to get icon name back from live object */
+       return EINA_FALSE;
+     }
+   else if (!strcmp(param->name, "label on"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            const char *on, *off;
+            elm_toggle_states_labels_get(obj, &on, &off);
+            param->s = on;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "label off"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
+         {
+            const char *on, *off;
+            elm_toggle_states_labels_get(obj, &on, &off);
+            param->s = off;
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "state"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+         {
+            param->i = elm_toggle_state_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_toggle_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Toggle *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Toggle));
+   if (!mem)
+     return NULL;
+
+   external_common_icon_param_parse(&mem->icon, obj, params);
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "state")) {
+          mem->state = param->i;
+          mem->state_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "label on"))
+         mem->on = eina_stringshare_add(param->s);
+       else if (!strcmp(param->name, "label off"))
+         mem->off = eina_stringshare_add(param->s);
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_toggle_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_toggle_params_free(void *params)
+{
+   Elm_Params_Toggle *mem = params;
+
+   if (mem->on)
+     eina_stringshare_del(mem->on);
+   if (mem->off)
+     eina_stringshare_del(mem->off);
+   if (mem->label)
+      eina_stringshare_del(mem->label);
+   free(params);
+}
+
+static Edje_External_Param_Info external_toggle_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_STRING("label"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING("icon"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("label on", "ON"),
+   EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("label off", "OFF"),
+   EDJE_EXTERNAL_PARAM_INFO_BOOL("state"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(toggle, "toggle")
+DEFINE_EXTERNAL_TYPE_SIMPLE(toggle, "Toggle")
diff --git a/src/edje_externals/elm_toolbar.c b/src/edje_externals/elm_toolbar.c
new file mode 100644 (file)
index 0000000..18d5d84
--- /dev/null
@@ -0,0 +1,129 @@
+#include "private.h"
+
+typedef struct _Elm_Params_Toolbar
+{
+   Elm_Params base;
+   int icon_size;
+   Eina_Bool icon_size_exists:1;
+   double align;
+   Eina_Bool align_exists:1;
+} Elm_Params_Toolbar;
+
+static void
+external_toolbar_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__)
+{
+   const Elm_Params_Toolbar *p;
+
+   if (to_params) p = to_params;
+   else if (from_params) p = from_params;
+   else return;
+
+   if (p->icon_size_exists)
+     elm_toolbar_icon_size_set(obj, p->icon_size);
+   if (p->align_exists)
+     elm_toolbar_align_set(obj, p->align);
+}
+
+static Eina_Bool
+external_toolbar_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "icon_size"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            elm_toolbar_icon_size_set(obj, param->i);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "align"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            elm_toolbar_align_set(obj, param->d);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+external_toolbar_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param)
+{
+   if (!strcmp(param->name, "icon_size"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT)
+         {
+            param->i = elm_toolbar_icon_size_get(obj);
+            return EINA_TRUE;
+         }
+     }
+   else if (!strcmp(param->name, "align"))
+     {
+       if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
+         {
+            param->d = elm_toolbar_align_get(obj);
+            return EINA_TRUE;
+         }
+     }
+
+   ERR("unknown parameter '%s' of type '%s'",
+       param->name, edje_external_param_type_str(param->type));
+
+   return EINA_FALSE;
+}
+
+static void *
+external_toolbar_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params)
+{
+   Elm_Params_Toolbar *mem;
+   Edje_External_Param *param;
+   const Eina_List *l;
+
+   mem = calloc(1, sizeof(Elm_Params_Toolbar));
+   if (!mem)
+     return NULL;
+
+   EINA_LIST_FOREACH(params, l, param)
+     {
+       if (!strcmp(param->name, "icon_size"))
+         {
+            mem->icon_size = param->i;
+            mem->icon_size_exists = EINA_TRUE;
+         }
+       else if (!strcmp(param->name, "align"))
+         {
+            mem->align = param->d;
+            mem->align_exists = EINA_TRUE;
+         }
+     }
+
+   return mem;
+}
+
+static Evas_Object *external_toolbar_content_get(void *data __UNUSED__,
+               const Evas_Object *obj __UNUSED__, const char *content __UNUSED__)
+{
+       ERR("No content.");
+       return NULL;
+}
+
+static void
+external_toolbar_params_free(void *params)
+{
+   Elm_Params_Toolbar *mem = params;
+   free(mem);
+}
+
+static Edje_External_Param_Info external_toolbar_params[] = {
+   DEFINE_EXTERNAL_COMMON_PARAMS,
+   EDJE_EXTERNAL_PARAM_INFO_INT("icon_size"),
+   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("align"),
+   EDJE_EXTERNAL_PARAM_INFO_SENTINEL
+};
+
+DEFINE_EXTERNAL_ICON_ADD(toolbar, "toolbar");
+DEFINE_EXTERNAL_TYPE_SIMPLE(toolbar, "Toolbar");
diff --git a/src/edje_externals/modules.inc b/src/edje_externals/modules.inc
new file mode 100644 (file)
index 0000000..941fe95
--- /dev/null
@@ -0,0 +1,28 @@
+DEFINE_TYPE(anchorblock)
+DEFINE_TYPE(anchorview)
+DEFINE_TYPE(bubble)
+DEFINE_TYPE(button)
+DEFINE_TYPE(check)
+DEFINE_TYPE(clock)
+DEFINE_TYPE(fileselector)
+DEFINE_TYPE(fileselector_button)
+DEFINE_TYPE(fileselector_entry)
+DEFINE_TYPE(genlist)
+DEFINE_TYPE(hoversel)
+DEFINE_TYPE(list)
+DEFINE_TYPE(map)
+DEFINE_TYPE(photocam)
+DEFINE_TYPE(progressbar)
+DEFINE_TYPE(radio)
+DEFINE_TYPE(scrolled_entry)
+DEFINE_TYPE(slider)
+DEFINE_TYPE(slideshow)
+DEFINE_TYPE(spinner)
+DEFINE_TYPE(thumb)
+DEFINE_TYPE(toggle)
+DEFINE_TYPE(toolbar)
+DEFINE_TYPE(notify)
+DEFINE_TYPE(panes)
+DEFINE_TYPE(label)
+DEFINE_TYPE(icon)
+DEFINE_TYPE(scroller)
diff --git a/src/edje_externals/private.h b/src/edje_externals/private.h
new file mode 100644 (file)
index 0000000..6bf0274
--- /dev/null
@@ -0,0 +1,118 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include "Elementary.h"
+#include "elm_priv.h"
+
+typedef struct {
+    const char *style;
+} Elm_Params;
+
+void external_elm_init(void);
+void external_signal(void *data, Evas_Object *obj, const char *signal, const char *source);
+void external_signals_proxy(Evas_Object *obj, Evas_Object *edje, const char *part_name);
+const char *external_translate(void *data, const char *orig);
+void external_common_params_free(void *params);
+void *external_common_params_parse_internal(size_t params_size, void *data, Evas_Object *obj, const Eina_List *params);
+Evas_Object *external_common_param_icon_get(Evas_Object *obj, const Edje_External_Param *param);
+Evas_Object *external_common_param_edje_object_get(Evas_Object *obj, const Edje_External_Param *p);
+void external_common_icon_param_parse(Evas_Object **icon, Evas_Object *obj, const Eina_List *params);
+Eina_Bool external_common_param_get(void *data, const Evas_Object *obj, Edje_External_Param *param);
+Eina_Bool external_common_param_set(void *data, Evas_Object *obj, const Edje_External_Param *param);
+void external_common_state_set(void *data, Evas_Object *obj, const void *from_params, const void *to_params, float pos);
+void external_common_params_parse(void *mem, void *data, Evas_Object *obj, const Eina_List *params);
+
+#define DEFINE_EXTERNAL_TYPE(type_name, name)           \
+static Eina_Bool                                        \
+_external_##type_name##_param_set(void *data, Evas_Object *obj, const Edje_External_Param *param) \
+{                                                       \
+   if (external_common_param_set(data, obj, param))     \
+      return EINA_TRUE;                                 \
+   return external_##type_name##_param_set(data, obj, param); \
+}                                                       \
+static Eina_Bool                                        \
+_external_##type_name##_param_get(void *data, const Evas_Object *obj, Edje_External_Param *param) \
+{                                                       \
+   if (external_common_param_get(data, obj, param))     \
+      return EINA_TRUE;                                 \
+   return external_##type_name##_param_get(data, obj, param); \
+}                                                       \
+static const char *                                     \
+external_##type_name##_label_get(void *data __UNUSED__) \
+{                                                       \
+    return name;                                        \
+}                                                       \
+                                                        \
+static void                                             \
+_external_##type_name##_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__) \
+{                                                       \
+   external_common_state_set(data, obj, from_params, to_params, pos); \
+   external_##type_name##_state_set(data, obj, from_params, to_params, pos); \
+}                                                       \
+                                                        \
+static void *                                           \
+_external_##type_name##_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params) \
+{                                                       \
+   void *mem = external_##type_name##_params_parse(data, obj, params); \
+   external_common_params_parse(mem, data, obj, params); \
+   return mem;                                          \
+}                                                       \
+static void                                             \
+_external_##type_name##_params_free(void *params)       \
+{                                                       \
+   external_common_params_free(params);                 \
+   external_##type_name##_params_free(params);          \
+}                                                       \
+                                                        \
+const Edje_External_Type external_##type_name##_type = {\
+    .abi_version = EDJE_EXTERNAL_TYPE_ABI_VERSION,      \
+    .module = "elm",                                    \
+    .module_name = "Elementary",                        \
+    .add = external_##type_name##_add,                  \
+    .state_set = _external_##type_name##_state_set,     \
+    .signal_emit = external_signal,                     \
+    .param_set = _external_##type_name##_param_set,     \
+    .param_get = _external_##type_name##_param_get,     \
+    .params_parse = _external_##type_name##_params_parse,\
+    .params_free = _external_##type_name##_params_free, \
+    .label_get = external_##type_name##_label_get,      \
+    .content_get = external_##type_name##_content_get,  \
+    .description_get = NULL,                            \
+    .icon_add = external_##type_name##_icon_add,        \
+    .preview_add = NULL,                                \
+    .translate = external_translate,                    \
+    .parameters_info = external_##type_name##_params,   \
+    .data = NULL                                        \
+};
+
+#define DEFINE_EXTERNAL_TYPE_SIMPLE(type_name, name)    \
+static Evas_Object *                                \
+external_##type_name##_add(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *edje, const Eina_List *params __UNUSED__, const char *part_name) \
+{                                                                      \
+   Evas_Object *parent, *obj;                                          \
+   external_elm_init();                                                 \
+   parent = elm_widget_parent_widget_get(edje);                        \
+   if (!parent) parent = edje;                                         \
+   obj = elm_##type_name##_add(parent);                                \
+   external_signals_proxy(obj, edje, part_name);                       \
+   return obj;                                                         \
+}                                                                      \
+                                                                       \
+DEFINE_EXTERNAL_TYPE(type_name, name)
+
+#define DEFINE_EXTERNAL_ICON_ADD(type_name, name)                   \
+Evas_Object *                                                       \
+external_##type_name##_icon_add(void *data __UNUSED__, Evas *e) {   \
+   Evas_Object *ic;                                                 \
+   int w = 20, h = 10;                                              \
+                                                                    \
+   ic = edje_object_add(e);                                         \
+   edje_object_file_set(ic, PACKAGE_DATA_DIR"/edje_externals/icons.edj", "ico_"name);\
+   evas_object_size_hint_min_set(ic, w, h);                         \
+   evas_object_size_hint_max_set(ic, w, h);                         \
+                                                                    \
+   return ic;                                                       \
+}
+
+#define DEFINE_EXTERNAL_COMMON_PARAMS           \
+    EDJE_EXTERNAL_PARAM_INFO_STRING_DEFAULT("style", "default")
diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in
new file mode 100644 (file)
index 0000000..0ae22f3
--- /dev/null
@@ -0,0 +1,2647 @@
+/*
+ *
+ * vim:ts=8:sw=3:sts=3:expandtab:cino=>5n-2f0^-2{2(0W1st0
+ */
+#ifndef ELEMENTARY_H
+#define ELEMENTARY_H
+
+/**
+ * @file Elementary.h
+ * @brief Elementary's API
+ *
+ * Elementary API.
+ */
+
+@ELM_UNIX_DEF@ ELM_UNIX
+@ELM_WIN32_DEF@ ELM_WIN32
+@ELM_WINCE_DEF@ ELM_WINCE
+@ELM_EDBUS_DEF@ ELM_EDBUS
+@ELM_EFREET_DEF@ ELM_EFREET
+@ELM_ETHUMB_DEF@ ELM_ETHUMB
+@ELM_DEBUG_DEF@ ELM_DEBUG
+@ELM_ALLOCA_H_DEF@ ELM_ALLOCA_H
+@ELM_LIBINTL_H_DEF@ ELM_LIBINTL_H
+
+/* Standard headers for standard system calls etc. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <dlfcn.h>
+#include <math.h>
+#include <fnmatch.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <errno.h>
+
+#ifdef ELM_UNIX
+# include <locale.h>
+# ifdef ELM_LIBINTL_H
+#  include <libintl.h>
+# endif
+# include <signal.h>
+# include <grp.h>
+# include <glob.h>
+#endif
+
+#ifdef ELM_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#if defined (ELM_WIN32) || defined (ELM_WINCE)
+# include <malloc.h>
+# ifndef alloca
+#  define alloca _alloca
+# endif
+#endif
+
+
+/* EFL headers */
+#include <Eina.h>
+#include <Eet.h>
+#include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Ecore_File.h>
+#include <Ecore_IMF.h>
+#include <Edje.h>
+
+#ifdef ELM_EDBUS
+# include <E_DBus.h>
+#endif
+
+#ifdef ELM_EFREET
+# include <Efreet.h>
+# include <Efreet_Mime.h>
+# include <Efreet_Trash.h>
+#endif
+
+#ifdef ELM_ETHUMB
+# include <Ethumb_Client.h>
+#endif
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef ELEMENTARY_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_EVAS_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+
+/* allow usage from c++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ELM_VERSION_MAJOR @VMAJ@
+#define ELM_VERSION_MINOR @VMIN@
+
+   typedef struct _Elm_Version
+     {
+        int major;
+        int minor;
+        int micro;
+        int revision;
+     } Elm_Version;
+
+   EAPI extern Elm_Version *elm_version;
+
+/* handy macros */
+#define ELM_RECTS_INTERSECT(x, y, w, h, xx, yy, ww, hh) (((x) < ((xx) + (ww))) && ((y) < ((yy) + (hh))) && (((x) + (w)) > (xx)) && (((y) + (h)) > (yy)))
+#define ELM_PI 3.14159265358979323846
+
+  /**
+   * Defines couple of standard Evas_Object layers to be used
+   * with evas_object_layer_set().
+   *
+   * @note whenever extending with new values, try to keep some padding
+   *       to siblings so there is room for further extensions.
+   */
+  typedef enum _Elm_Object_Layer
+    {
+       ELM_OBJECT_LAYER_BACKGROUND = EVAS_LAYER_MIN + 64, /**< where to place backgrounds */
+       ELM_OBJECT_LAYER_DEFAULT = 0, /**< Evas_Object default layer (and thus for Elementary) */
+       ELM_OBJECT_LAYER_FOCUS = EVAS_LAYER_MAX - 128, /**< where focus object visualization is */
+       ELM_OBJECT_LAYER_TOOLTIP = EVAS_LAYER_MAX - 64, /**< where to show tooltips */
+       ELM_OBJECT_LAYER_CURSOR = EVAS_LAYER_MAX - 32, /**< where to show cursors */
+       ELM_OBJECT_LAYER_LAST /**< last layer known by Elementary */
+    } Elm_Object_Layer;
+
+/**************************************************************************/
+   EAPI extern int ELM_ECORE_EVENT_ETHUMB_CONNECT;
+
+   /* Objects */
+   /**
+    * Emitted when policy value changed.
+    */
+   EAPI extern int ELM_EVENT_POLICY_CHANGED;
+   typedef struct _Elm_Event_Policy_Changed
+     {
+        unsigned int policy;
+        int          new_value;
+        int          old_value;
+     } Elm_Event_Policy_Changed;
+
+   /**
+    * Policy identifiers.
+    *
+    * @see elm_policy_set()
+    */
+   typedef enum _Elm_Policy
+     {
+       ELM_POLICY_QUIT, /**< when should quit application automatically.
+                         * @see Elm_Policy_Quit.
+                         */
+       ELM_POLICY_LAST
+     } Elm_Policy;
+
+   typedef enum _Elm_Policy_Quit
+     {
+        ELM_POLICY_QUIT_NONE = 0, /**< never quit application automatically */
+        ELM_POLICY_QUIT_LAST_WINDOW_CLOSED /**< quit when last window is closed */
+     } Elm_Policy_Quit;
+
+   typedef enum _Elm_Focus_Direction
+     {
+        ELM_FOCUS_PREVIOUS,
+        ELM_FOCUS_NEXT
+     } Elm_Focus_Direction;
+
+   typedef enum _Elm_Text_Format
+     {
+        ELM_TEXT_FORMAT_PLAIN_UTF8,
+        ELM_TEXT_FORMAT_MARKUP_UTF8
+     } Elm_Text_Format;
+
+   /**
+    * Called back when a widget's tooltip is activated and needs content.
+    * @param data user-data given to elm_object_tooltip_content_cb_set()
+    * @param obj owner widget.
+    */
+   typedef Evas_Object *(*Elm_Tooltip_Content_Cb) (void *data, Evas_Object *obj);
+
+   /**
+    * Called back when a widget's item tooltip is activated and needs content.
+    * @param data user-data given to elm_object_tooltip_content_cb_set()
+    * @param obj owner widget.
+    * @param item context dependent item. As an example, if tooltip was
+    *        set on Elm_List_Item, then it is of this type.
+    */
+   typedef Evas_Object *(*Elm_Tooltip_Item_Content_Cb) (void *data, Evas_Object *obj, void *item);
+
+   typedef Eina_Bool (*Elm_Event_Cb) (void *data, Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info);
+
+#ifndef ELM_LIB_QUICKLAUNCH
+#define ELM_MAIN() int main(int argc, char **argv) {elm_init(argc, argv); return elm_main(argc, argv);}
+#else
+#define ELM_MAIN() int main(int argc, char **argv) {return elm_quicklaunch_fallback(argc, argv);}
+#endif
+
+/**************************************************************************/
+   /* General calls */
+   EAPI int          elm_init(int argc, char **argv);
+   EAPI int          elm_shutdown(void);
+   EAPI void         elm_run(void);
+   EAPI void         elm_exit(void);
+
+   EAPI void         elm_quicklaunch_mode_set(Eina_Bool ql_on);
+   EAPI Eina_Bool    elm_quicklaunch_mode_get(void);
+   EAPI int          elm_quicklaunch_init(int argc, char **argv);
+   EAPI int          elm_quicklaunch_sub_init(int argc, char **argv);
+   EAPI int          elm_quicklaunch_sub_shutdown(void);
+   EAPI int          elm_quicklaunch_shutdown(void);
+   EAPI void         elm_quicklaunch_seed(void);
+   EAPI Eina_Bool    elm_quicklaunch_prepare(int argc, char **argv);
+   EAPI Eina_Bool    elm_quicklaunch_fork(int argc, char **argv, char *cwd, void (postfork_func) (void *data), void *postfork_data);
+   EAPI void         elm_quicklaunch_cleanup(void);
+   EAPI int          elm_quicklaunch_fallback(int argc, char **argv);
+   EAPI char        *elm_quicklaunch_exe_path_get(const char *exe);
+
+   EAPI Eina_Bool    elm_need_efreet(void);
+   EAPI Eina_Bool    elm_need_e_dbus(void);
+   EAPI Eina_Bool    elm_need_ethumb(void);
+
+   EAPI Eina_Bool    elm_policy_set(unsigned int policy, int value);
+   EAPI int          elm_policy_get(unsigned int policy);
+
+   EAPI void         elm_all_flush(void);
+   EAPI int          elm_cache_flush_interval_get(void);
+   EAPI void         elm_cache_flush_interval_set(int size);
+   EAPI void         elm_cache_flush_interval_all_set(int size);
+   EAPI Eina_Bool    elm_cache_flush_enmabled_get(void);
+   EAPI void         elm_cache_flush_enabled_set(Eina_Bool enabled);
+   EAPI void         elm_cache_flush_enabled_all_set(Eina_Bool enabled);
+   EAPI int          elm_font_cache_get(void);
+   EAPI void         elm_font_cache_set(int size);
+   EAPI void         elm_font_cache_all_set(int size);
+   EAPI int          elm_image_cache_get(void);
+   EAPI void         elm_image_cache_set(int size);
+   EAPI void         elm_image_cache_all_set(int size);
+   EAPI int          elm_edje_file_cache_get(void);
+   EAPI void         elm_edje_file_cache_set(int size);
+   EAPI void         elm_edje_file_cache_all_set(int size);
+   EAPI int          elm_edje_collection_cache_get(void);
+   EAPI void         elm_edje_collection_cache_set(int size);
+   EAPI void         elm_edje_collection_cache_all_set(int size);
+
+   EAPI void         elm_object_scale_set(Evas_Object *obj, double scale) EINA_ARG_NONNULL(1);
+   EAPI double       elm_object_scale_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_style_set(Evas_Object *obj, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_object_style_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_disabled_set(Evas_Object *obj, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_object_disabled_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI Eina_Bool    elm_object_widget_check(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_object_parent_widget_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_object_top_widget_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_object_widget_type_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI double       elm_scale_get(void);
+   EAPI void         elm_scale_set(double scale);
+   EAPI void         elm_scale_all_set(double scale);
+
+   EAPI Eina_Bool    elm_config_save(void);
+   EAPI void         elm_config_reload(void);
+
+   EAPI const char  *elm_profile_current_get(void);
+   EAPI const char  *elm_profile_dir_get(const char *profile, Eina_Bool is_user);
+   EAPI void         elm_profile_dir_free(const char *p_dir);
+   EAPI Eina_List   *elm_profile_list_get(void);
+   EAPI void         elm_profile_list_free(Eina_List *l);
+   EAPI void         elm_profile_set(const char *profile);
+   EAPI void         elm_profile_all_set(const char *profile);
+
+   EAPI const char  *elm_engine_current_get(void);
+   EAPI void         elm_engine_set(const char *engine);
+
+  typedef struct _Elm_Text_Class
+    {
+       const char *name;
+       const char *desc;
+    } Elm_Text_Class;
+
+  typedef struct _Elm_Font_Overlay
+    {
+       const char     *text_class;
+       const char     *font;
+       Evas_Font_Size  size;
+    } Elm_Font_Overlay;
+
+  typedef struct _Elm_Font_Properties
+    {
+       const char *name;
+       Eina_List  *styles;
+    } Elm_Font_Properties;
+
+   EAPI const Eina_List     *elm_text_classes_list_get(void);
+   EAPI void                 elm_text_classes_list_free(const Eina_List *list);
+
+   EAPI const Eina_List     *elm_font_overlay_list_get(void);
+   EAPI void                 elm_font_overlay_set(const char *text_class, const char *font, Evas_Font_Size size);
+   EAPI void                 elm_font_overlay_unset(const char *text_class);
+   EAPI void                 elm_font_overlay_apply(void);
+   EAPI void                 elm_font_overlay_all_apply(void);
+
+   EAPI Elm_Font_Properties *elm_font_properties_get(const char *font) EINA_ARG_NONNULL(1);
+   EAPI void                 elm_font_properties_free(Elm_Font_Properties *efp) EINA_ARG_NONNULL(1);
+   EAPI const char          *elm_font_fontconfig_name_get(const char *name, const char *style) EINA_ARG_NONNULL(1);
+   EAPI void                 elm_font_fontconfig_name_free(const char *name) EINA_ARG_NONNULL(1);
+   EAPI Eina_Hash           *elm_font_available_hash_add(Eina_List *list);
+   EAPI void                 elm_font_available_hash_del(Eina_Hash *hash);
+
+   EAPI Evas_Coord       elm_finger_size_get(void);
+   EAPI void             elm_finger_size_set(Evas_Coord size);
+   EAPI void             elm_finger_size_all_set(Evas_Coord size);
+
+   EAPI Eina_Bool        elm_focus_highlight_enabled_get(void);
+   EAPI void             elm_focus_highlight_enabled_set(Eina_Bool enable);
+   EAPI Eina_Bool        elm_focus_highlight_animate_get(void);
+   EAPI void             elm_focus_highlight_animate_set(Eina_Bool animate);
+
+   EAPI Eina_Bool        elm_object_focus_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_focus(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_unfocus(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_focus_allow_set(Evas_Object *obj, Eina_Bool enable) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_object_focus_allow_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI void             elm_object_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_focus_custom_chain_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List *elm_object_focus_custom_chain_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child) EINA_ARG_NONNULL(1, 2);
+   EAPI void             elm_object_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child) EINA_ARG_NONNULL(1, 2);
+   EAPI void             elm_object_focus_cycle(Evas_Object *obj, Elm_Focus_Direction dir) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_focus_direction_go(Evas_Object *obj, int x, int y) EINA_ARG_NONNULL(1);
+
+   EAPI Eina_Bool        elm_scroll_bounce_enabled_get(void);
+   EAPI void             elm_scroll_bounce_enabled_set(Eina_Bool enabled);
+   EAPI void             elm_scroll_bounce_enabled_all_set(Eina_Bool enabled);
+   EAPI double           elm_scroll_bounce_friction_get(void);
+   EAPI void             elm_scroll_bounce_friction_set(double friction);
+   EAPI void             elm_scroll_bounce_friction_all_set(double friction);
+   EAPI double           elm_scroll_page_scroll_friction_get(void);
+   EAPI void             elm_scroll_page_scroll_friction_set(double friction);
+   EAPI void             elm_scroll_page_scroll_friction_all_set(double friction);
+   EAPI double           elm_scroll_bring_in_scroll_friction_get(void);
+   EAPI void             elm_scroll_bring_in_scroll_friction_set(double friction);
+   EAPI void             elm_scroll_bring_in_scroll_friction_all_set(double friction);
+   EAPI double           elm_scroll_zoom_friction_get(void);
+   EAPI void             elm_scroll_zoom_friction_set(double friction);
+   EAPI void             elm_scroll_zoom_friction_all_set(double friction);
+   EAPI Eina_Bool        elm_scroll_thumbscroll_enabled_get(void);
+   EAPI void             elm_scroll_thumbscroll_enabled_set(Eina_Bool enabled);
+   EAPI void             elm_scroll_thumbscroll_enabled_all_set(Eina_Bool enabled);
+   EAPI unsigned int     elm_scroll_thumbscroll_threshold_get(void);
+   EAPI void             elm_scroll_thumbscroll_threshold_set(unsigned int threshold);
+   EAPI void             elm_scroll_thumbscroll_threshold_all_set(unsigned int threshold);
+   EAPI double           elm_scroll_thumbscroll_momentum_threshold_get(void);
+   EAPI void             elm_scroll_thumbscroll_momentum_threshold_set(double threshold);
+   EAPI void             elm_scroll_thumbscroll_momentum_threshold_all_set(double threshold);
+   EAPI double           elm_scroll_thumbscroll_friction_get(void);
+   EAPI void             elm_scroll_thumbscroll_friction_set(double friction);
+   EAPI void             elm_scroll_thumbscroll_friction_all_set(double friction);
+   EAPI double           elm_scroll_thumbscroll_border_friction_get(void);
+   EAPI void             elm_scroll_thumbscroll_border_friction_set(double friction);
+   EAPI void             elm_scroll_thumbscroll_border_friction_all_set(double friction);
+
+   EAPI void             elm_object_scroll_hold_push(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_scroll_hold_pop(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_scroll_freeze_push(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_scroll_freeze_pop(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_scroll_lock_x_set(Evas_Object *obj, Eina_Bool lock) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_scroll_lock_y_set(Evas_Object *obj, Eina_Bool lock) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_object_scroll_lock_x_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_object_scroll_lock_y_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI void             elm_object_signal_emit(Evas_Object *obj, const char *emission, const char *source) EINA_ARG_NONNULL(1);
+   EAPI void             elm_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data) EINA_ARG_NONNULL(1, 4);
+   EAPI void            *elm_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source)) EINA_ARG_NONNULL(1, 4);
+
+   EAPI void             elm_object_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void            *elm_object_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 2);
+
+   EAPI void             elm_coords_finger_size_adjust(int times_w, Evas_Coord *w, int times_h, Evas_Coord *h);
+
+   EAPI double           elm_longpress_timeout_get(void);
+   EAPI void             elm_longpress_timeout_set(double longpress_timeout);
+
+   /* debug
+    * don't use it unless you are sure
+    */
+   EAPI void             elm_object_tree_dump(const Evas_Object *top);
+   EAPI void             elm_object_tree_dot_dump(const Evas_Object *top, const char *file);
+
+
+   /* theme */
+   typedef struct _Elm_Theme Elm_Theme;
+
+   EAPI Elm_Theme       *elm_theme_new(void);
+   EAPI void             elm_theme_free(Elm_Theme *th);
+   EAPI void             elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst);
+   EAPI void             elm_theme_ref_set(Elm_Theme *th, Elm_Theme *thref);
+   EAPI Elm_Theme       *elm_theme_ref_get(Elm_Theme *th);
+   EAPI Elm_Theme       *elm_theme_default_get(void);
+   EAPI void             elm_theme_overlay_add(Elm_Theme *th, const char *item);
+   EAPI void             elm_theme_overlay_del(Elm_Theme *th, const char *item);
+   EAPI void             elm_theme_extension_add(Elm_Theme *th, const char *item);
+   EAPI void             elm_theme_extension_del(Elm_Theme *th, const char *item);
+   EAPI void             elm_theme_set(Elm_Theme *th, const char *theme);
+   EAPI const char      *elm_theme_get(Elm_Theme *th);
+   EAPI const Eina_List *elm_theme_list_get(const Elm_Theme *th);
+   EAPI char            *elm_theme_list_item_path_get(const char *f, Eina_Bool *in_search_path);
+   EAPI void             elm_theme_flush(Elm_Theme *th);
+   EAPI void             elm_theme_full_flush(void);
+
+   EAPI void             elm_theme_all_set(const char *theme);
+
+   EAPI Eina_List       *elm_theme_name_available_list_new(void);
+   EAPI void             elm_theme_name_available_list_free(Eina_List *list);
+
+   EAPI void             elm_object_theme_set(Evas_Object *obj, Elm_Theme *th) EINA_ARG_NONNULL(1);
+   EAPI Elm_Theme       *elm_object_theme_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* win */
+   typedef enum _Elm_Win_Type
+     {
+        ELM_WIN_BASIC,
+        ELM_WIN_DIALOG_BASIC,
+        ELM_WIN_DESKTOP,
+        ELM_WIN_DOCK,
+        ELM_WIN_TOOLBAR,
+        ELM_WIN_MENU,
+        ELM_WIN_UTILITY,
+        ELM_WIN_SPLASH
+     } Elm_Win_Type;
+
+   typedef enum _Elm_Win_Keyboard_Mode
+     {
+       ELM_WIN_KEYBOARD_UNKNOWN,
+        ELM_WIN_KEYBOARD_OFF,
+        ELM_WIN_KEYBOARD_ON,
+        ELM_WIN_KEYBOARD_ALPHA,
+        ELM_WIN_KEYBOARD_NUMERIC,
+        ELM_WIN_KEYBOARD_PIN,
+        ELM_WIN_KEYBOARD_PHONE_NUMBER,
+        ELM_WIN_KEYBOARD_HEX,
+        ELM_WIN_KEYBOARD_TERMINAL,
+        ELM_WIN_KEYBOARD_PASSWORD,
+        ELM_WIN_KEYBOARD_IP,
+        ELM_WIN_KEYBOARD_HOST,
+        ELM_WIN_KEYBOARD_FILE,
+        ELM_WIN_KEYBOARD_URL,
+        ELM_WIN_KEYBOARD_KEYPAD,
+        ELM_WIN_KEYBOARD_J2ME
+     } Elm_Win_Keyboard_Mode;
+
+   EAPI Evas_Object *elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type);
+   EAPI void         elm_win_resize_object_add(Evas_Object *obj, Evas_Object *subobj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_resize_object_del(Evas_Object *obj, Evas_Object *subobj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_title_set(Evas_Object *obj, const char *title) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_win_title_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_autodel_set(Evas_Object *obj, Eina_Bool autodel) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_autodel_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_activate(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_lower(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_raise(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_borderless_set(Evas_Object *obj, Eina_Bool borderless) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_borderless_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_shaped_set(Evas_Object *obj, Eina_Bool shaped) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_shaped_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_alpha_set(Evas_Object *obj, Eina_Bool alpha) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_transparent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_transparent_set(Evas_Object *obj, Eina_Bool transparent) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_alpha_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_override_set(Evas_Object *obj, Eina_Bool override) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_override_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_fullscreen_set(Evas_Object *obj, Eina_Bool fullscreen) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_fullscreen_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_maximized_set(Evas_Object *obj, Eina_Bool maximized) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_maximized_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_iconified_set(Evas_Object *obj, Eina_Bool iconified) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_iconified_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_layer_set(Evas_Object *obj, int layer) EINA_ARG_NONNULL(1);
+   EAPI int          elm_win_layer_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_rotation_set(Evas_Object *obj, int rotation) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_rotation_with_resize_set(Evas_Object *obj, int rotation) EINA_ARG_NONNULL(1);
+   EAPI int          elm_win_rotation_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_sticky_set(Evas_Object *obj, Eina_Bool sticky) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_sticky_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_conformant_set(Evas_Object *obj, Eina_Bool conformant) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_conformant_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_quickpanel_set(Evas_Object *obj, Eina_Bool quickpanel) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_quickpanel_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_quickpanel_priority_major_set(Evas_Object *obj, int priority) EINA_ARG_NONNULL(1);
+   EAPI int          elm_win_quickpanel_priority_major_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_quickpanel_priority_minor_set(Evas_Object *obj, int priority) EINA_ARG_NONNULL(1);
+   EAPI int          elm_win_quickpanel_priority_minor_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_quickpanel_zone_set(Evas_Object *obj, int zone) EINA_ARG_NONNULL(1);
+   EAPI int          elm_win_quickpanel_zone_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_focus_highlight_enabled_set(Evas_Object *obj, Eina_Bool enabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_win_focus_highlight_enabled_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_win_focus_highlight_style_set(Evas_Object *obj, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_win_focus_highlight_style_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /*...
+    * ecore_x_icccm_hints_set -> accepts_focus (add to ecore_evas)
+    * ecore_x_icccm_hints_set -> window_group (add to ecore_evas)
+    * ecore_x_icccm_size_pos_hints_set -> request_pos (add to ecore_evas)
+    * ecore_x_icccm_client_leader_set -> l (add to ecore_evas)
+    * ecore_x_icccm_window_role_set -> role (add to ecore_evas)
+    * ecore_x_icccm_transient_for_set -> forwin (add to ecore_evas)
+    * ecore_x_netwm_window_type_set -> type (add to ecore_evas)
+    *
+    * (add to ecore_x) set netwm argb icon! (add to ecore_evas)
+    * (blank mouse, private mouse obj, defaultmouse)
+    *
+    */
+   EAPI void                  elm_win_keyboard_mode_set(Evas_Object *obj, Elm_Win_Keyboard_Mode mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_Win_Keyboard_Mode elm_win_keyboard_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_win_keyboard_win_set(Evas_Object *obj, Eina_Bool is_keyboard) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_win_keyboard_win_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI void                  elm_win_screen_position_get(const Evas_Object *obj, int *x, int *y) EINA_ARG_NONNULL(1);
+
+   EAPI Evas_Object          *elm_win_inwin_add(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_win_inwin_activate(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_win_inwin_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_win_inwin_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_win_inwin_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* available styles:
+    * default
+    * minimal
+    * minimal_vertical
+    */
+   /* X specific calls - won't work on non-x engines (return 0) */
+   EAPI Ecore_X_Window elm_win_xwindow_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "delete,request" - the user requested to delete the window
+    * "focus,in" - window got focus
+    * "focus,out" - window lost focus
+    * "moved" - window that holds the canvas was moved
+    */
+
+   /* bg */
+   typedef enum _Elm_Bg_Option
+     {
+        ELM_BG_OPTION_CENTER,  /**< center the background */
+        ELM_BG_OPTION_SCALE,   /**< scale the background retaining aspect ratio */
+        ELM_BG_OPTION_STRETCH, /**< stretch the background to fill */
+        ELM_BG_OPTION_TILE     /**< tile background at its original size */
+     } Elm_Bg_Option;
+
+   EAPI Evas_Object  *elm_bg_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void          elm_bg_file_set(Evas_Object *obj, const char *file, const char *group) EINA_ARG_NONNULL(1);
+   EAPI void          elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group) EINA_ARG_NONNULL(1);
+   EAPI void          elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option) EINA_ARG_NONNULL(1);
+   EAPI Elm_Bg_Option elm_bg_option_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void          elm_bg_color_set(Evas_Object *obj, int r, int g, int b) EINA_ARG_NONNULL(1);
+   EAPI void          elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b) EINA_ARG_NONNULL(1);
+   EAPI void          elm_bg_overlay_set(Evas_Object *obj, Evas_Object *overlay) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object  *elm_bg_overlay_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object  *elm_bg_overlay_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    */
+
+   /* icon */
+   typedef enum _Elm_Icon_Lookup_Order
+     {
+        ELM_ICON_LOOKUP_FDO_THEME, /**< icon look up order: freedesktop, theme */
+        ELM_ICON_LOOKUP_THEME_FDO, /**< icon look up order: theme, freedesktop */
+        ELM_ICON_LOOKUP_FDO,       /**< icon look up order: freedesktop */
+        ELM_ICON_LOOKUP_THEME      /**< icon look up order: theme */
+     } Elm_Icon_Lookup_Order;
+
+   EAPI Evas_Object          *elm_icon_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_icon_file_set(Evas_Object *obj, const char *file, const char *group) EINA_ARG_NONNULL(1, 2);
+   EAPI void                  elm_icon_file_get(const Evas_Object *obj, const char **file, const char **group) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_icon_standard_set(Evas_Object *obj, const char *name) EINA_ARG_NONNULL(1);
+   EAPI const char           *elm_icon_standard_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_icon_smooth_set(Evas_Object *obj, Eina_Bool smooth) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_icon_smooth_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_icon_no_scale_set(Evas_Object *obj, Eina_Bool no_scale) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_icon_no_scale_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_icon_scale_set(Evas_Object *obj, Eina_Bool scale_up, Eina_Bool scale_down) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_icon_scale_get(const Evas_Object *obj, Eina_Bool *scale_up, Eina_Bool *scale_down) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_icon_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_icon_fill_outside_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_icon_prescale_set(Evas_Object *obj, int size) EINA_ARG_NONNULL(1);
+   EAPI int                   elm_icon_prescale_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order) EINA_ARG_NONNULL(1);
+   EAPI Elm_Icon_Lookup_Order elm_icon_order_lookup_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - the user clicked the icon
+    */
+
+   /* image */
+   typedef enum _Elm_Image_Orient
+     {
+        ELM_IMAGE_ORIENT_NONE,
+        ELM_IMAGE_ROTATE_90_CW,
+        ELM_IMAGE_ROTATE_180_CW,
+        ELM_IMAGE_ROTATE_90_CCW,
+        ELM_IMAGE_FLIP_HORIZONTAL,
+        ELM_IMAGE_FLIP_VERTICAL,
+        ELM_IMAGE_FLIP_TRANSPOSE,
+        ELM_IMAGE_FLIP_TRANSVERSE
+     } Elm_Image_Orient;
+   EAPI Evas_Object     *elm_image_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_image_file_set(Evas_Object *obj, const char *file, const char *group) EINA_ARG_NONNULL(1, 2);
+   EAPI void             elm_image_file_get(const Evas_Object *obj, const char **file, const char **group) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_smooth_set(Evas_Object *obj, Eina_Bool smooth) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_image_smooth_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_object_size_get(const Evas_Object *obj, int *w, int *h) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_no_scale_set(Evas_Object *obj, Eina_Bool no_scale) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_image_no_scale_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_scale_set(Evas_Object *obj, Eina_Bool scale_up, Eina_Bool scale_down) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_scale_get(const Evas_Object *obj, Eina_Bool *scale_up, Eina_Bool *scale_down) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_image_fill_outside_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_prescale_set(Evas_Object *obj, int size) EINA_ARG_NONNULL(1);
+   EAPI int              elm_image_prescale_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_orient_set(Evas_Object *obj, Elm_Image_Orient orient) EINA_ARG_NONNULL(1);
+   EAPI Elm_Image_Orient elm_image_orient_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_image_editable_set(Evas_Object *obj, Eina_Bool set) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_image_editable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - the user clicked the image
+    */
+
+   /* box */
+   typedef struct _Elm_Box_Transition Elm_Box_Transition;
+
+   EAPI Evas_Object        *elm_box_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool           elm_box_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_homogenous_set(Evas_Object *obj, Eina_Bool homogenous) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool           elm_box_homogenous_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_pack_start(Evas_Object *obj, Evas_Object *subobj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_pack_end(Evas_Object *obj, Evas_Object *subobj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_pack_before(Evas_Object *obj, Evas_Object *subobj, Evas_Object *before) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_pack_after(Evas_Object *obj, Evas_Object *subobj, Evas_Object *after) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_unpack(Evas_Object *obj, Evas_Object *subobj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_unpack_all(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List    *elm_box_children_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_align_set(Evas_Object *obj, double horizontal, double vertical) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_align_get(const Evas_Object *obj, double *horizontal, double *vertical) EINA_ARG_NONNULL(1);
+
+   EAPI void                elm_box_layout_set(Evas_Object *obj, Evas_Object_Box_Layout cb, const void *data, void (*free_data)(void *data)) EINA_ARG_NONNULL(1);
+   EAPI void                elm_box_layout_transition(Evas_Object *obj, Evas_Object_Box_Data *priv, void *data);
+   EAPI Elm_Box_Transition *elm_box_transition_new(const double duration, Evas_Object_Box_Layout start_layout, void *start_layout_data, void(*start_layout_free_data)(void *data), Evas_Object_Box_Layout end_layout, void *end_layout_data, void(*end_layout_free_data)(void *data), void(*transition_end_cb)(void *data), void *transition_end_data) EINA_ARG_NONNULL(2, 5);
+   EAPI void                elm_box_transition_free(void *data);
+   /* smart callbacks called:
+    */
+
+   /* button */
+   EAPI Evas_Object *elm_button_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_button_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_button_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_button_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_button_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_button_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_button_autorepeat_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t) EINA_ARG_NONNULL(1);
+   EAPI double       elm_button_autorepeat_initial_timeout_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t) EINA_ARG_NONNULL(1);
+   EAPI double       elm_button_autorepeat_gap_timeout_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* available styles:
+    * default
+    * anchor
+    * hoversel_vertical
+    * hoversel_vertical_entry
+    */
+   /* smart callbacks called:
+    * "clicked" - the user clicked the button
+    * "repeated" - the user pressed the button without releasing it
+    * "unpressed" - when the button is unpressed (released)
+    */
+
+   /* fileselector */
+   EAPI Evas_Object *elm_fileselector_button_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_fileselector_button_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_fileselector_button_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_fileselector_button_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_window_title_set(Evas_Object *obj, const char *title) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_fileselector_button_window_title_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_window_size_set(Evas_Object *obj, Evas_Coord width, Evas_Coord height) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_window_size_get(const Evas_Object *obj, Evas_Coord *width, Evas_Coord *height) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_path_set(Evas_Object *obj, const char *path) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_fileselector_button_path_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_expandable_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_button_expandable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_folder_only_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_button_folder_only_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_is_save_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_button_is_save_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_button_inwin_mode_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_button_inwin_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* available styles:
+    * default
+    * anchor
+    * hoversel_vertical
+    * hoversel_vertical_entry
+    */
+   /* smart callbacks called:
+    * "file,chosen" - the user has selected a path, whose string pointer comes
+                      as event info
+    */
+
+   EAPI Evas_Object *elm_fileselector_entry_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_button_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_fileselector_entry_button_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_button_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_fileselector_entry_button_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_fileselector_entry_button_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_window_title_set(Evas_Object *obj, const char *title) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_fileselector_entry_window_title_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_window_size_set(Evas_Object *obj, Evas_Coord width, Evas_Coord height) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_window_size_get(const Evas_Object *obj, Evas_Coord *width, Evas_Coord *height) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_path_set(Evas_Object *obj, const char *path) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_fileselector_entry_path_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_expandable_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_entry_expandable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_folder_only_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_entry_folder_only_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_is_save_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_entry_is_save_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_inwin_mode_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_fileselector_entry_inwin_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_fileselector_entry_selected_set(Evas_Object *obj, const char *path) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_fileselector_entry_selected_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* scroller policy */
+   typedef enum _Elm_Scroller_Policy
+     {
+        ELM_SCROLLER_POLICY_AUTO = 0,
+        ELM_SCROLLER_POLICY_ON,
+        ELM_SCROLLER_POLICY_OFF,
+        ELM_SCROLLER_POLICY_LAST
+     } Elm_Scroller_Policy;
+
+   EAPI Evas_Object *elm_scroller_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_content_set(Evas_Object *obj, Evas_Object *child) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_scroller_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_scroller_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_custom_widget_base_theme_set(Evas_Object *obj, const char *widget, const char *base) EINA_ARG_NONNULL(1, 2, 3);
+   EAPI void         elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_child_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation);
+   EAPI Eina_Bool    elm_scroller_propagate_events_get(const Evas_Object *obj);
+
+   /* smart callbacks called:
+    * "edge,left"
+    * "edge,right"
+    * "edge,top"
+    * "edge,bottom"
+    * "scroll"
+    * "scroll,anim,start"
+    * "scroll,anim,stop"
+    * "scroll,drag,start"
+    * "scroll,drag,stop"
+    */
+
+   /* label */
+   EAPI Evas_Object *elm_label_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_label_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_line_wrap_set(Evas_Object *obj, Eina_Bool wrap) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_label_line_wrap_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w) EINA_ARG_NONNULL(1);
+   EAPI Evas_Coord   elm_label_wrap_width_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_wrap_height_set(Evas_Object *obj, Evas_Coord h) EINA_ARG_NONNULL(1);
+   EAPI Evas_Coord   elm_label_wrap_height_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_fontsize_set(Evas_Object *obj, int fontsize) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_text_align_set(Evas_Object *obj, const char *alignmode) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_slide_set(Evas_Object *obj, Eina_Bool slide) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_label_slide_get(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_label_slide_duration_set(Evas_Object *obj, double duration) EINA_ARG_NONNULL(1);
+   EAPI double       elm_label_slide_duration_get(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* available styles:
+    * default
+    * marker
+    */
+   /* smart callbacks called:
+    */
+
+   /* toggle */
+   EAPI Evas_Object *elm_toggle_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_toggle_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_toggle_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_toggle_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_toggle_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_toggle_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_toggle_states_labels_set(Evas_Object *obj, const char *onlabel, const char *offlabel) EINA_ARG_NONNULL(1);
+   EAPI void         elm_toggle_states_labels_get(const Evas_Object *obj, const char **onlabel, const char **offlabel) EINA_ARG_NONNULL(1);
+   EAPI void         elm_toggle_state_set(Evas_Object *obj, Eina_Bool state) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_toggle_state_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_toggle_state_pointer_set(Evas_Object *obj, Eina_Bool *statep) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "changed" - the user toggled the state
+    */
+
+   /* frame */
+   EAPI Evas_Object *elm_frame_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_frame_label_set(Evas_Object *obj, const char *label); EINA_ARG_NONNULL(1)
+   EAPI const char  *elm_frame_label_get(const Evas_Object *obj); EINA_ARG_NONNULL(1)
+   EAPI void         elm_frame_content_set(Evas_Object *obj, Evas_Object *content); EINA_ARG_NONNULL(1)
+   EAPI Evas_Object *elm_frame_content_get(const Evas_Object *obj); EINA_ARG_NONNULL(1)
+   EAPI Evas_Object *elm_frame_content_unset(Evas_Object *obj); EINA_ARG_NONNULL(1)
+   /* available styles:
+    * default
+    * pad_small
+    * pad_medium
+    * pad_large
+    * pad_huge
+    * outdent_top
+    * outdent_bottom
+    */
+   /* smart callbacks called:
+    */
+
+   /* table */
+   EAPI Evas_Object *elm_table_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_table_homogenous_set(Evas_Object *obj, Eina_Bool homogenous) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_table_homogeneous_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void        elm_table_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical) EINA_ARG_NONNULL(1);
+   EAPI void         elm_table_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical) EINA_ARG_NONNULL(1);
+   EAPI void         elm_table_pack(Evas_Object *obj, Evas_Object *subobj, int x, int y, int w, int h) EINA_ARG_NONNULL(1);
+   EAPI void         elm_table_unpack(Evas_Object *obj, Evas_Object *subobj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_table_clear(Evas_Object *obj, Eina_Bool clear) EINA_ARG_NONNULL(1);
+
+   /* gengrid */
+   typedef struct _Elm_Gengrid_Item_Class Elm_Gengrid_Item_Class;
+   typedef struct _Elm_Gengrid_Item_Class_Func Elm_Gengrid_Item_Class_Func;
+   typedef struct _Elm_Gengrid_Item Elm_Gengrid_Item; /**< Item of Elm_Gengrid. Sub-type of Elm_Widget_Item */
+   typedef char        *(*GridItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part);
+   typedef Evas_Object *(*GridItemIconGetFunc)  (void *data, Evas_Object *obj, const char *part);
+   typedef Eina_Bool    (*GridItemStateGetFunc) (void *data, Evas_Object *obj, const char *part);
+   typedef void         (*GridItemDelFunc)      (void *data, Evas_Object *obj);
+
+   struct _Elm_Gengrid_Item_Class
+     {
+       const char             *item_style;
+       struct _Elm_Gengrid_Item_Class_Func {
+          GridItemLabelGetFunc  label_get;
+          GridItemIconGetFunc   icon_get;
+          GridItemStateGetFunc  state_get;
+          GridItemDelFunc       del;
+        } func;
+     };
+
+   EAPI Evas_Object       *elm_gengrid_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_align_set(Evas_Object *obj, double align_x, double align_y) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_align_get(const Evas_Object *obj, double *align_x, double *align_y) EINA_ARG_NONNULL(1);
+
+   EAPI void               elm_gengrid_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_gengrid_always_select_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_gengrid_no_select_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_multi_select_set(Evas_Object *obj, Eina_Bool multi) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_gengrid_multi_select_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_horizontal_set(Evas_Object *obj, Eina_Bool setting) EINA_ARG_NONNULL(1);
+
+   EAPI Elm_Gengrid_Item  *elm_gengrid_first_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Gengrid_Item  *elm_gengrid_last_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI Elm_Gengrid_Item  *elm_gengrid_item_next_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Gengrid_Item  *elm_gengrid_item_prev_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_gengrid_item_gengrid_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_del(Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_update(Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void              *elm_gengrid_item_data_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_data_set(Elm_Gengrid_Item *item, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_pos_get(const Elm_Gengrid_Item *item, unsigned int *x, unsigned int *y) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_selected_set(Elm_Gengrid_Item *item, Eina_Bool selected) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_gengrid_item_selected_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object *elm_gengrid_item_object_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_show(Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_bring_in(Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_disabled_set(Elm_Gengrid_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_gengrid_item_disabled_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+
+   EAPI void               elm_gengrid_item_tooltip_text_set(Elm_Gengrid_Item *item, const char *text) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_tooltip_content_cb_set(Elm_Gengrid_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_tooltip_unset(Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_tooltip_style_set(Elm_Gengrid_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_gengrid_item_tooltip_style_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_cursor_set(Elm_Gengrid_Item *item, const char *cursor) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_gengrid_item_cursor_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_cursor_unset(Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_cursor_style_set(Elm_Gengrid_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_gengrid_item_cursor_style_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_cursor_engine_only_set(Elm_Gengrid_Item *item, Eina_Bool engine_only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_gengrid_item_cursor_engine_only_get(const Elm_Gengrid_Item *item) EINA_ARG_NONNULL(1);
+
+   EAPI void              elm_gengrid_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Gengrid_Item  *elm_gengrid_selected_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List   *elm_gengrid_selected_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI Elm_Gengrid_Item  *elm_gengrid_item_append(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic,  const void *data, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Gengrid_Item  *elm_gengrid_item_prepend(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic, const void *data, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Gengrid_Item  *elm_gengrid_item_insert_before(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic, const void *data, Elm_Gengrid_Item *relative, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Gengrid_Item  *elm_gengrid_item_insert_after(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic, const void *data, Elm_Gengrid_Item *relative, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    *
+    * selected - User has selected a item.
+    * unselected - User has unselected a item.
+    * clicked - User has double-clicked a item.
+    * realized - An evas object for a item was built.
+    * unrealized - An evas object for a item was deleted.
+    * changed - An item has been added, removed, resized or moved,
+    * or gengrid has been resized or horizontal property has been changed.
+    * scroll - the content has been scrolled (moved).
+    * "scroll,drag,start" - dragging the contents around has started.
+    * "scroll,drat,stop" - dragging the contents around has stopped.
+    * drag - Gengrid is being dragged.
+    * "drag,start,up" - Gengrid has been dragged (not scrolled) up.
+    * "drag,start,down" - Gengrid has been dragged (not scrolled) down.
+    * "drag,start,left" - Gengrid has been dragged (not scrolled) left.
+    * "drag,start,rigth" - Gengrid has been dragged (nto scrolled) right.
+    * "drag,stop" - Gengrid is not being dragged.
+    */
+
+   /* clock */
+   typedef enum _Elm_Clock_Digedit
+     {
+        ELM_CLOCK_NONE         = 0,
+        ELM_CLOCK_HOUR_DECIMAL = 1 << 0,
+        ELM_CLOCK_HOUR_UNIT    = 1 << 1,
+        ELM_CLOCK_MIN_DECIMAL  = 1 << 2,
+        ELM_CLOCK_MIN_UNIT     = 1 << 3,
+        ELM_CLOCK_SEC_DECIMAL  = 1 << 4,
+        ELM_CLOCK_SEC_UNIT     = 1 << 5,
+        ELM_CLOCK_ALL         = (1 << 6) - 1
+     } Elm_Clock_Digedit;
+
+   EAPI Evas_Object      *elm_clock_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void              elm_clock_time_set(Evas_Object *obj, int hrs, int min, int sec) EINA_ARG_NONNULL(1);
+   EAPI void              elm_clock_time_get(const Evas_Object *obj, int *hrs, int *min, int *sec) EINA_ARG_NONNULL(1);
+   EAPI void              elm_clock_edit_set(Evas_Object *obj, Eina_Bool edit) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_clock_edit_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_clock_digit_edit_set(Evas_Object *obj, Elm_Clock_Digedit digedit) EINA_ARG_NONNULL(1);
+   EAPI Elm_Clock_Digedit elm_clock_digit_edit_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_clock_show_am_pm_set(Evas_Object *obj, Eina_Bool am_pm) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_clock_show_am_pm_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_clock_show_seconds_set(Evas_Object *obj, Eina_Bool seconds) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_clock_show_seconds_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_clock_interval_set(Evas_Object *obj, double interval) EINA_ARG_NONNULL(1);
+   EAPI double           elm_clock_interval_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "changed" - the user changed the time
+    */
+
+   /* layout */
+   EAPI Evas_Object       *elm_layout_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_layout_file_set(Evas_Object *obj, const char *file, const char *group) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_layout_theme_set(Evas_Object *obj, const char *clas, const char *group, const char *style) EINA_ARG_NONNULL(1);
+   EAPI void               elm_layout_content_set(Evas_Object *obj, const char *swallow, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object *elm_layout_content_get(const Evas_Object *obj, const char *swallow) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_layout_content_unset(Evas_Object *obj, const char *swallow) EINA_ARG_NONNULL(1);
+   EAPI void               elm_layout_text_set(Evas_Object *obj, const char *part, const char *text) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_layout_text_get(const Evas_Object *obj, const char *part) EINA_ARG_NONNULL(1);
+   EAPI void               elm_layout_box_append(Evas_Object *obj, const char *part, Evas_Object *child) EINA_ARG_NONNULL(1);
+   EAPI void               elm_layout_box_prepend(Evas_Object *obj, const char *part, Evas_Object *child) EINA_ARG_NONNULL(1);
+   EAPI void               elm_layout_box_insert_before(Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference) EINA_ARG_NONNULL(1);
+   EAPI void               elm_layout_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_layout_box_remove(Evas_Object *obj, const char *part, Evas_Object *child) EINA_ARG_NONNULL(1, 2, 3);
+   EAPI void               elm_layout_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool clear) EINA_ARG_NONNULL(1, 2);
+   EAPI void               elm_layout_table_pack(Evas_Object *obj, const char *part, Evas_Object *child_obj, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_layout_table_unpack(Evas_Object *obj, const char *part, Evas_Object *child_obj) EINA_ARG_NONNULL(1, 2, 3);
+   EAPI void               elm_layout_table_clear(Evas_Object *obj, const char *part, Eina_Bool clear) EINA_ARG_NONNULL(1, 2);
+   EAPI Evas_Object       *elm_layout_edje_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_layout_data_get(const Evas_Object *obj, const char *key) EINA_ARG_NONNULL(1, 2);
+   EAPI void               elm_layout_sizing_eval(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_layout_part_cursor_set(Evas_Object *obj, const char *part_name, const char *cursor) EINA_ARG_NONNULL(1, 2);
+   EAPI const char        *elm_layout_part_cursor_get(const Evas_Object *obj, const char *part_name) EINA_ARG_NONNULL(1, 2);
+   EAPI void               elm_layout_part_cursor_unset(Evas_Object *obj, const char *part_name) EINA_ARG_NONNULL(1, 2);
+   EAPI Eina_Bool          elm_layout_part_cursor_style_set(Evas_Object *obj, const char *part_name, const char *style) EINA_ARG_NONNULL(1, 2);
+   EAPI const char        *elm_layout_part_cursor_style_get(const Evas_Object *obj, const char *part_name) EINA_ARG_NONNULL(1, 2);
+   EAPI Eina_Bool          elm_layout_part_cursor_engine_only_set(Evas_Object *obj, const char *part_name, Eina_Bool engine_only) EINA_ARG_NONNULL(1, 2);
+   EAPI Eina_Bool          elm_layout_part_cursor_engine_only_get(const Evas_Object *obj, const char *part_name) EINA_ARG_NONNULL(1, 2);
+/**
+ * @def elm_layout_icon_set
+ * Convienience macro to set the icon object in a layout that follows the
+ * Elementary naming convention for its parts.
+ *
+ * @ingroup Layout
+ */
+#define elm_layout_icon_set(_ly, _obj) \
+  do { \
+    const char *sig; \
+    elm_layout_content_set((_ly), "elm.swallow.icon", (_obj)); \
+    if ((_obj)) sig = "elm,state,icon,visible"; \
+    else sig = "elm,state,icon,hidden"; \
+    elm_object_signal_emit((_ly), sig, "elm"); \
+  } while (0)
+
+/**
+ * @def elm_layout_icon_get
+ * Convienience macro to get the icon object from a layout that follows the
+ * Elementary naming convention for its parts.
+ *
+ * @ingroup Layout
+ */
+#define elm_layout_icon_get(_ly) \
+  elm_layout_content_get((_ly), "elm.swallow.icon")
+
+/**
+ * @def elm_layout_end_set
+ * Convienience macro to set the end object in a layout that follows the
+ * Elementary naming convention for its parts.
+ *
+ * @ingroup Layout
+ */
+#define elm_layout_end_set(_ly, _obj) \
+  do { \
+    const char *sig; \
+    elm_layout_content_set((_ly), "elm.swallow.end", (_obj)); \
+    if ((_obj)) sig = "elm,state,end,visible"; \
+    else sig = "elm,state,end,hidden"; \
+    elm_object_signal_emit((_ly), sig, "elm"); \
+  } while (0)
+
+/**
+ * @def elm_layout_end_get
+ * Convienience macro to get the end object in a layout that follows the
+ * Elementary naming convention for its parts.
+ *
+ * @ingroup Layout
+ */
+#define elm_layout_end_get(_ly) \
+  elm_layout_content_get((_ly), "elm.swallow.end")
+
+/**
+ * @def elm_layout_label_set
+ * Convienience macro to set the label in a layout that follows the
+ * Elementary naming convention for its parts.
+ *
+ * @ingroup Layout
+ */
+#define elm_layout_label_set(_ly, _txt) \
+  elm_layout_text_set((_ly), "elm.text", (_txt))
+
+/**
+ * @def elm_layout_label_get
+ * Convienience macro to get the label in a layout that follows the
+ * Elementary naming convention for its parts.
+ *
+ * @ingroup Layout
+ */
+#define elm_layout_label_get(_ly) \
+  elm_layout_text_get((_ly), "elm.text")
+
+   /* smart callbacks called:
+    */
+
+   /* notify */
+   typedef enum _Elm_Notify_Orient
+     {
+        ELM_NOTIFY_ORIENT_TOP,
+        ELM_NOTIFY_ORIENT_CENTER,
+        ELM_NOTIFY_ORIENT_BOTTOM,
+        ELM_NOTIFY_ORIENT_LEFT,
+        ELM_NOTIFY_ORIENT_RIGHT,
+        ELM_NOTIFY_ORIENT_TOP_LEFT,
+        ELM_NOTIFY_ORIENT_TOP_RIGHT,
+        ELM_NOTIFY_ORIENT_BOTTOM_LEFT,
+        ELM_NOTIFY_ORIENT_BOTTOM_RIGHT,
+        ELM_NOTIFY_ORIENT_LAST
+     } Elm_Notify_Orient;
+   EAPI Evas_Object      *elm_notify_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void              elm_notify_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object      *elm_notify_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object      *elm_notify_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object      *elm_notify_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient) EINA_ARG_NONNULL(1);
+   EAPI Elm_Notify_Orient elm_notify_orient_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_notify_timeout_set(Evas_Object *obj, double timeout) EINA_ARG_NONNULL(1);
+   EAPI double            elm_notify_timeout_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_notify_repeat_events_set(Evas_Object *obj, Eina_Bool repeat) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_notify_repeat_events_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "timeout" - when timeout happens on notify and it's hidden
+    * "block,clicked" - when it's hidden by a click outside of the notify's view
+    */
+
+   /* hover */
+   typedef enum _Elm_Hover_Axis
+     {
+        ELM_HOVER_AXIS_NONE,
+        ELM_HOVER_AXIS_HORIZONTAL,
+        ELM_HOVER_AXIS_VERTICAL,
+        ELM_HOVER_AXIS_BOTH
+     } Elm_Hover_Axis;
+   EAPI Evas_Object *elm_hover_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_hover_target_set(Evas_Object *obj, Evas_Object *target) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_hover_target_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_hover_content_set(Evas_Object *obj, const char *swallow, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_hover_content_get(const Evas_Object *obj, const char *swallow) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_hover_content_unset(Evas_Object *obj, const char *swallow) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_hover_best_content_location_get(const Evas_Object *obj, Elm_Hover_Axis pref_axis) EINA_ARG_NONNULL(1);
+   /* available styles:
+    * default
+    * popout
+    * menu
+    * hoversel_vertical
+    */
+   /* smart callbacks called:
+    * "clicked" - the user clicked the empty space in the hover to dismiss
+    * "smart,changed" - a content object placed under the "smart"
+    *                   policy was replaced to a new slot direction.
+    */
+
+   /* entry */
+   typedef struct _Elm_Entry_Anchor_Info Elm_Entry_Anchor_Info;
+   struct _Elm_Entry_Anchor_Info
+     {
+       const char *name;
+       int         button;
+       Evas_Coord  x, y, w, h;
+     };
+   typedef enum _Elm_Icon_Type
+     {
+        ELM_ICON_NONE,
+        ELM_ICON_FILE,
+        ELM_ICON_STANDARD
+     } Elm_Icon_Type;
+   typedef struct _Elm_Hoversel_Item Elm_Hoversel_Item; /**< Item of Elm_Hoversel. Sub-type of Elm_Widget_Item */
+
+   EAPI Evas_Object *elm_entry_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_single_line_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_password_set(Evas_Object *obj, Eina_Bool password) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_password_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_entry_set(Evas_Object *obj, const char *entry) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_entry_entry_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_is_empty(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_entry_selection_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_entry_insert(Evas_Object *obj, const char *entry) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_line_wrap_set(Evas_Object *obj, Eina_Bool wrap) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_line_char_wrap_set(Evas_Object *obj, Eina_Bool wrap) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_editable_set(Evas_Object *obj, Eina_Bool editable) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_editable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_select_none(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_select_all(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cursor_next(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cursor_prev(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cursor_up(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cursor_down(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_cursor_begin_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_cursor_end_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_cursor_line_begin_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_cursor_line_end_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_cursor_selection_begin(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_cursor_selection_end(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cursor_is_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cursor_is_visible_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_entry_cursor_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cursor_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_selection_cut(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_selection_copy(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_selection_paste(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_context_menu_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_context_menu_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_context_menu_disabled_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI char        *elm_entry_markup_to_utf8(const char *s);
+   EAPI char        *elm_entry_utf8_to_markup(const char *s);
+   EAPI void         elm_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_file_save(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_autosave_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_entry_cnp_textonly_set(Evas_Object *obj, Eina_Bool textonly) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_entry_cnp_textonly_get(Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* pre-made filters for entries */
+   typedef struct _Elm_Entry_Filter_Limit_Size Elm_Entry_Filter_Limit_Size;
+   struct _Elm_Entry_Filter_Limit_Size
+     {
+        int max_char_count;
+        int max_byte_count;
+     };
+   EAPI void         elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text) EINA_ARG_NONNULL(1, 2, 3);
+   typedef struct _Elm_Entry_Filter_Accept_Set Elm_Entry_Filter_Accept_Set;
+   struct _Elm_Entry_Filter_Accept_Set
+     {
+        const char *accepted;
+        const char *rejected;
+     };
+   EAPI void         elm_entry_filter_accept_set(void *data, Evas_Object *entry, char **text) EINA_ARG_NONNULL(1, 3);
+   /* smart callbacks called:
+    * "changed" - the text content changed
+    * "selection,start" - the user started selecting text
+    * "selection,changed" - the user modified the selection size/location
+    * "selection,cleared" - the user cleared the selection
+    * "selection,paste" - the user requested a paste of text
+    * "selection,copy" - the user copied the text
+    * "selection,cut" - the user cut the text
+    * "cursor,changed" - the cursor changed position
+    * "anchor,clicked" - achor called was clicked | event_info = Elm_Entry_Anchor_Info
+    * "activated" - when the enter key is pressed (useful for single line)
+    * "press" - when finger/mouse is pressed down
+    * "clicked" - when finger/mouse is pressed and released (without a drag etc.)
+    * "clicked,double" - when finger/mouse is double-pressed
+    * "longpressed" - the entry has been longpressed
+    * "focused" - the entry has received keyboard focus
+    * "unfocused" - keyboard focus is gone
+    */
+
+   /* composite widgets - these basically put together basic widgets above
+    * in convenient packages that do more than basic stuff */
+
+   /* anchorview */
+   typedef struct _Elm_Entry_Anchorview_Info Elm_Entry_Anchorview_Info;
+   struct _Elm_Entry_Anchorview_Info
+     {
+       const char     *name;
+       int             button;
+       Evas_Object    *hover;
+        struct {
+          Evas_Coord    x, y, w, h;
+        } anchor, hover_parent;
+       Eina_Bool       hover_left : 1;
+       Eina_Bool       hover_right : 1;
+       Eina_Bool       hover_top : 1;
+       Eina_Bool       hover_bottom : 1;
+     };
+   EAPI Evas_Object *elm_anchorview_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorview_text_set(Evas_Object *obj, const char *text) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_anchorview_text_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI void         elm_anchorview_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_anchorview_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorview_hover_style_set(Evas_Object *obj, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_anchorview_hover_style_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorview_hover_end(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorview_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorview_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorview_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_anchorview_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_anchorview_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   /* smart callbacks called:
+    * "anchor,clicked" - achor called was clicked | event_info = Elm_Entry_Anchorview_Info
+    */
+
+   /* anchorblock */
+   typedef struct _Elm_Entry_Anchorblock_Info Elm_Entry_Anchorblock_Info;
+   struct _Elm_Entry_Anchorblock_Info
+     {
+       const char     *name;
+       int             button;
+       Evas_Object    *hover;
+       struct {
+          Evas_Coord    x, y, w, h;
+        } anchor, hover_parent;
+       Eina_Bool       hover_left : 1;
+       Eina_Bool       hover_right : 1;
+       Eina_Bool       hover_top : 1;
+       Eina_Bool       hover_bottom : 1;
+     };
+   EAPI Evas_Object *elm_anchorblock_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorblock_text_set(Evas_Object *obj, const char *text) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_anchorblock_text_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorblock_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_anchorblock_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorblock_hover_style_set(Evas_Object *obj, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_anchorblock_hover_style_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorblock_hover_end(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_anchorblock_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorblock, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_anchorblock_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorblock, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_anchorblock_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorblock, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   /* smart callbacks called:
+    * "anchor,clicked" - achor called was clicked | event_info = Elm_Entry_Anchorblock_Info
+    */
+
+   /* bubble */
+   EAPI Evas_Object *elm_bubble_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_bubble_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_bubble_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_bubble_info_set(Evas_Object *obj, const char *info) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_bubble_info_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   EAPI void         elm_bubble_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_bubble_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_bubble_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_bubble_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_bubble_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_bubble_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_bubble_corner_set(Evas_Object *obj, const char *corner) EINA_ARG_NONNULL(1, 2);
+   EAPI const char  *elm_bubble_corner_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - the user clicked the bubble
+    */
+
+   /* photo */
+   EAPI Evas_Object *elm_photo_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_photo_file_set(Evas_Object *obj, const char *file) EINA_ARG_NONNULL(1);
+   EAPI void         elm_photo_size_set(Evas_Object *obj, int size) EINA_ARG_NONNULL(1);
+   EAPI void         elm_photo_fill_inside_set(Evas_Object *obj, Eina_Bool fill) EINA_ARG_NONNULL(1);
+   EAPI void         elm_photo_editable_set(Evas_Object *obj, Eina_Bool set) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - the user clicked the icon
+    */
+
+   /* thumb */
+   typedef enum _Elm_Thumb_Animation_Setting
+     {
+        ELM_THUMB_ANIMATION_START = 0, /* Play animation once */
+        ELM_THUMB_ANIMATION_LOOP,      /* Keep playing animation until stop is requested */
+        ELM_THUMB_ANIMATION_STOP,
+        ELM_THUMB_ANIMATION_LAST
+     } Elm_Thumb_Animation_Setting;
+
+   EAPI Evas_Object                 *elm_thumb_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                         elm_thumb_reload(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                        elm_thumb_file_set(Evas_Object *obj, const char *file, const char *key) EINA_ARG_NONNULL(1);
+   EAPI void                        elm_thumb_file_get(const Evas_Object *obj, const char **file, const char **key) EINA_ARG_NONNULL(1);
+   EAPI void                        elm_thumb_path_get(const Evas_Object *obj, const char **file, const char **key) EINA_ARG_NONNULL(1);
+   EAPI void                        elm_thumb_animate_set(Evas_Object *obj, Elm_Thumb_Animation_Setting s) EINA_ARG_NONNULL(1);
+   EAPI Elm_Thumb_Animation_Setting  elm_thumb_animate_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                        *elm_thumb_ethumb_client_get(void);
+   EAPI Eina_Bool                    elm_thumb_ethumb_client_connected(void);
+   EAPI Eina_Bool                    elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                    elm_thumb_editable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* available styles:
+    * default
+    * noframe
+    *
+    * smart callbacks called:
+    * "clicked" - the user clicked the thumb
+    * "clicked,double" - the user double clicked the thumb
+    * "press" - the user pressed the thumb
+    * "generate,start" - the thumbnail generation started
+    * "generate,stop" - the thumbnail generation stopped
+    * "generate,error" - the thumbnail generation failed
+    * "load,error" - the thumbnail image loading failed
+    */
+
+   /* hoversel */
+   EAPI Evas_Object       *elm_hoversel_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_hoversel_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_hoversel_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_hoversel_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_hoversel_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_hoversel_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_hover_begin(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_hover_end(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_hoversel_expanded_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List   *elm_hoversel_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Hoversel_Item *elm_hoversel_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_item_del(Elm_Hoversel_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_item_del_cb_set(Elm_Hoversel_Item *it, Evas_Smart_Cb func) EINA_ARG_NONNULL(1);
+   EAPI void              *elm_hoversel_item_data_get(const Elm_Hoversel_Item *it) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_hoversel_item_label_get(const Elm_Hoversel_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_item_icon_set(Elm_Hoversel_Item *it, const char *icon_file, const char *icon_group, Elm_Icon_Type icon_type) EINA_ARG_NONNULL(1);
+   EAPI void               elm_hoversel_item_icon_get(const Elm_Hoversel_Item *it, const char **icon_file, const char **icon_group, Elm_Icon_Type *icon_type) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - the user clicked the hoversel button and popped up the sel
+    * "selected" - an item in the hoversel list is selected
+    * "dismissed" - the hover is dismissed
+    */
+
+   /* toolbar */
+   typedef enum _Elm_Toolbar_Shrink_Mode
+     {
+        ELM_TOOLBAR_SHRINK_NONE,   /**< set toolbar minimun size to fit all the items */
+        ELM_TOOLBAR_SHRINK_HIDE,   /**< hide excess items */
+        ELM_TOOLBAR_SHRINK_SCROLL, /**< allow accessing excess items through a scroller */
+        ELM_TOOLBAR_SHRINK_MENU    /**< inserts a button to pop up a menu with excess items */
+     } Elm_Toolbar_Shrink_Mode;
+
+   typedef struct _Elm_Toolbar_Item Elm_Toolbar_Item; /**< Item of Elm_Toolbar. Sub-type of Elm_Widget_Item */
+   typedef struct _Elm_Toolbar_Item_State Elm_Toolbar_Item_State; /** State of a Elm_Toolbar_Item */
+
+   EAPI Evas_Object            *elm_toolbar_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_icon_size_set(Evas_Object *obj, int icon_size) EINA_ARG_NONNULL(1);
+   EAPI int                     elm_toolbar_icon_size_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order) EINA_ARG_NONNULL(1);
+   EAPI Elm_Icon_Lookup_Order   elm_toolbar_icon_order_lookup_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_no_select_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_item_append(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_item_prepend(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_item_insert_before(Evas_Object *obj, Elm_Toolbar_Item *before, const char *icon, const char *label, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_item_insert_after(Evas_Object *obj, Elm_Toolbar_Item *after, const char *icon, const char *label, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_first_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_last_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_item_next_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_item_prev_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object            *elm_toolbar_item_toolbar_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_priority_set(Elm_Toolbar_Item *item, int priority) EINA_ARG_NONNULL(1);
+   EAPI int                     elm_toolbar_item_priority_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI const char             *elm_toolbar_item_icon_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI const char             *elm_toolbar_item_label_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_label_set(Elm_Toolbar_Item *item, const char *label) EINA_ARG_NONNULL(1);
+   EAPI void                   *elm_toolbar_item_data_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_data_set(Elm_Toolbar_Item *item, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_item_find_by_label(const Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_item_selected_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_selected_set(Elm_Toolbar_Item *item, Eina_Bool selected) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item       *elm_toolbar_selected_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_icon_set(Elm_Toolbar_Item *item, const char *icon) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_del(Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_del_cb_set(Elm_Toolbar_Item *item, Evas_Smart_Cb func) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_item_disabled_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_disabled_set(Elm_Toolbar_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_separator_set(Elm_Toolbar_Item *item, Eina_Bool separator) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_item_separator_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_mode_shrink_set(Evas_Object *obj, Elm_Toolbar_Shrink_Mode shrink_mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Shrink_Mode elm_toolbar_mode_shrink_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_homogenous_set(Evas_Object *obj, Eina_Bool homogenous) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_homogenous_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_menu_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object            *elm_toolbar_menu_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_align_set(Evas_Object *obj, double align) EINA_ARG_NONNULL(1);
+   EAPI double                  elm_toolbar_align_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_menu_set(Elm_Toolbar_Item *item, Eina_Bool menu) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object            *elm_toolbar_item_menu_get(Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_add(Elm_Toolbar_Item *item, const char *icon, const char *label, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_item_state_del(Elm_Toolbar_Item *item, Elm_Toolbar_Item_State *state) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_item_state_set(Elm_Toolbar_Item *it, Elm_Toolbar_Item_State *state) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_state_unset(Elm_Toolbar_Item *it) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_get(const Elm_Toolbar_Item *it) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_next(Elm_Toolbar_Item *it) EINA_ARG_NONNULL(1);
+   EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_prev(Elm_Toolbar_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_tooltip_text_set(Elm_Toolbar_Item *item, const char *text) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_tooltip_content_cb_set(Elm_Toolbar_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_tooltip_unset(Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_tooltip_style_set(Elm_Toolbar_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char             *elm_toolbar_item_tooltip_style_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_cursor_set(Elm_Toolbar_Item *item, const char *cursor) EINA_ARG_NONNULL(1);
+   EAPI const char             *elm_toolbar_item_cursor_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_cursor_unset(Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_cursor_style_set(Elm_Toolbar_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char             *elm_toolbar_item_cursor_style_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                    elm_toolbar_item_cursor_engine_only_set(Elm_Toolbar_Item *item, Eina_Bool engine_only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool               elm_toolbar_item_cursor_engine_only_get(const Elm_Toolbar_Item *item) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - when the user clicks on a toolbar item and becomes selected
+    */
+   /* available styles:
+    * default
+    * transparent (no background or shadow, just show the provided content)
+    */
+
+   /* tooltip */
+   EAPI double       elm_tooltip_delay_get(void);
+   EAPI Eina_Bool    elm_tooltip_delay_set(double delay);
+   EAPI void         elm_object_tooltip_show(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_tooltip_hide(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_tooltip_text_set(Evas_Object *obj, const char *text) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_tooltip_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_tooltip_style_set(Evas_Object *obj, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_object_tooltip_style_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_cursor_set(Evas_Object *obj, const char *cursor) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_object_cursor_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_cursor_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_cursor_style_set(Evas_Object *obj, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_object_cursor_style_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_object_cursor_engine_only_set(Evas_Object *obj, Eina_Bool engine_only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_object_cursor_engine_only_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* cursors */
+   EAPI int          elm_cursor_engine_only_get(void);
+   EAPI Eina_Bool    elm_cursor_engine_only_set(int engine_only);
+
+   /* menu */
+   typedef struct _Elm_Menu_Item Elm_Menu_Item; /**< Item of Elm_Menu. Sub-type of Elm_Widget_Item */
+   EAPI Evas_Object       *elm_menu_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_menu_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_menu_object_get(const Elm_Menu_Item *it) EINA_ARG_NONNULL(1);
+   EAPI Elm_Menu_Item     *elm_menu_item_add(Evas_Object *obj, Elm_Menu_Item *parent, const char *icon, const char *label, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_item_label_set(Elm_Menu_Item *item, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_menu_item_label_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_item_icon_set(Elm_Menu_Item *item, const char *icon) EINA_ARG_NONNULL(1, 2);
+   EAPI const char        *elm_menu_item_icon_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object *elm_menu_item_object_icon_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_item_disabled_set(Elm_Menu_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_menu_item_disabled_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Menu_Item     *elm_menu_item_separator_add(Evas_Object *obj, Elm_Menu_Item *parent) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_menu_item_is_separator(Elm_Menu_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_item_del(Elm_Menu_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_item_del_cb_set(Elm_Menu_Item *it, Evas_Smart_Cb func) EINA_ARG_NONNULL(1);
+   EAPI void              *elm_menu_item_data_get(const Elm_Menu_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_menu_item_data_set(Elm_Menu_Item *item, const void *data) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List   *elm_menu_item_subitems_get(const Elm_Menu_Item *item) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - the user clicked the empty space in the menu to dismiss. event_info is NULL.
+    */
+
+   /* list */
+   typedef enum _Elm_List_Mode
+     {
+        ELM_LIST_COMPRESS = 0,
+        ELM_LIST_SCROLL,
+        ELM_LIST_LIMIT,
+        ELM_LIST_EXPAND,
+        ELM_LIST_LAST
+     } Elm_List_Mode;
+   typedef struct _Elm_List_Item Elm_List_Item; /**< Item of Elm_List. Sub-type of Elm_Widget_Item */
+   EAPI Evas_Object     *elm_list_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Item   *elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Item   *elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Item   *elm_list_item_insert_before(Evas_Object *obj, Elm_List_Item *before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI Elm_List_Item   *elm_list_item_insert_after(Evas_Object *obj, Elm_List_Item *after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI Elm_List_Item   *elm_list_item_sorted_insert(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_go(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_multi_select_set(Evas_Object *obj, Eina_Bool multi) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_list_multi_select_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Mode    elm_list_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_list_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool       elm_list_always_select_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List *elm_list_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Item   *elm_list_selected_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List *elm_list_selected_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_separator_set(Elm_List_Item *it, Eina_Bool setting) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_list_item_separator_get(const Elm_List_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_selected_set(Elm_List_Item *item, Eina_Bool selected) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_list_item_selected_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_show(Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_bring_in(Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_del(Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_del_cb_set(Elm_List_Item *item, Evas_Smart_Cb func) EINA_ARG_NONNULL(1);
+   EAPI void            *elm_list_item_data_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object     *elm_list_item_icon_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_icon_set(Elm_List_Item *item, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object     *elm_list_item_end_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_end_set(Elm_List_Item *item, Evas_Object *end) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object     *elm_list_item_base_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI const char      *elm_list_item_label_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_label_set(Elm_List_Item *item, const char *text) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Item   *elm_list_item_prev(const Elm_List_Item *it) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Item   *elm_list_item_next(const Elm_List_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_tooltip_text_set(Elm_List_Item *item, const char *text) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_tooltip_content_cb_set(Elm_List_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_tooltip_unset(Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_tooltip_style_set(Elm_List_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char      *elm_list_item_tooltip_style_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_cursor_set(Elm_List_Item *item, const char *cursor) EINA_ARG_NONNULL(1);
+   EAPI const char      *elm_list_item_cursor_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_cursor_unset(Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_cursor_style_set(Elm_List_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char      *elm_list_item_cursor_style_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_cursor_engine_only_set(Elm_List_Item *item, Eina_Bool engine_only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_list_item_cursor_engine_only_get(const Elm_List_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_item_disabled_set(Elm_List_Item *it, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool        elm_list_item_disabled_get(const Elm_List_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) EINA_ARG_NONNULL(1);
+   EAPI void             elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - when the user double-clicked an item
+    * "selected" - when the user selected an item
+    * "unselected" - when the user selected an item
+    * "longpressed" - an item in the hoversel list is long-pressed
+    * "scroll,edge,top" - the list is scrolled until the top edge
+    * "scroll,edge,bottom" - the list is scrolled until the bottom edge
+    * "scroll,edge,left" - the list is scrolled until the left edge
+    * "scroll,edge,right" - the list is scrolled until the right edge
+    */
+
+   /* slider */
+   EAPI Evas_Object       *elm_slider_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_slider_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_slider_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_slider_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_end_set(Evas_Object *obj, Evas_Object *end) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_slider_end_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_slider_end_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_span_size_set(Evas_Object *obj, Evas_Coord size) EINA_ARG_NONNULL(1);
+   EAPI Evas_Coord         elm_slider_span_size_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_unit_format_set(Evas_Object *obj, const char *format) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_slider_unit_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_slider_indicator_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_indicator_format_function_set(Evas_Object *obj, const char *(*func)(double val)) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_slider_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_min_max_set(Evas_Object *obj, double min, double max) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_min_max_get(const Evas_Object *obj, double *min, double *max) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_value_set(Evas_Object *obj, double val) EINA_ARG_NONNULL(1);
+   EAPI double             elm_slider_value_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_inverted_set(Evas_Object *obj, Eina_Bool inverted) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_slider_inverted_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_slider_indicator_show_set(Evas_Object *obj, Eina_Bool show) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_slider_indicator_show_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* actionslider */
+   typedef enum _Elm_Actionslider_Pos
+     {
+        ELM_ACTIONSLIDER_NONE = 0,
+        ELM_ACTIONSLIDER_LEFT = 1 << 0,
+        ELM_ACTIONSLIDER_CENTER = 1 << 1,
+        ELM_ACTIONSLIDER_RIGHT = 1 << 2,
+        ELM_ACTIONSLIDER_ALL = (1 << 3) -1
+     } Elm_Actionslider_Pos;
+
+   EAPI Evas_Object          *elm_actionslider_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_actionslider_labels_set(Evas_Object *obj, const char *left_label, const char *center_label, const char *right_label) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_actionslider_labels_get(const Evas_Object *obj, const char **left_label, const char **center_label, const char **right_label) EINA_ARG_NONNULL(1);
+   EAPI const char           *elm_actionslider_selected_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_actionslider_indicator_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos) EINA_ARG_NONNULL(1);
+   EAPI Elm_Actionslider_Pos  elm_actionslider_indicator_pos_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_actionslider_magnet_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos) EINA_ARG_NONNULL(1);
+   EAPI Elm_Actionslider_Pos  elm_actionslider_magnet_pos_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_actionslider_enabled_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos) EINA_ARG_NONNULL(1);
+   EAPI Elm_Actionslider_Pos  elm_actionslider_enabled_pos_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_actionslider_indicator_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char           *elm_actionslider_indicator_label_get(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "selected" - when user selects a position (the label is passed as
+    * event info)".
+    * "pos_changed" - when a button reaches to the special position like
+    * "left", "right" and "center".
+    */
+
+   /* genlist */
+   typedef enum _Elm_Genlist_Item_Flags
+     {
+        ELM_GENLIST_ITEM_NONE = 0,
+        ELM_GENLIST_ITEM_SUBITEMS = (1 << 0),
+        ELM_GENLIST_ITEM_GROUP = (1 << 1)
+     } Elm_Genlist_Item_Flags;
+   typedef struct _Elm_Genlist_Item_Class Elm_Genlist_Item_Class;
+   typedef struct _Elm_Genlist_Item       Elm_Genlist_Item; /**< Item of Elm_Genlist. Sub-type of Elm_Widget_Item */
+   typedef struct _Elm_Genlist_Item_Class_Func Elm_Genlist_Item_Class_Func;
+   typedef char        *(*GenlistItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part);
+   typedef Evas_Object *(*GenlistItemIconGetFunc)  (void *data, Evas_Object *obj, const char *part);
+   typedef Eina_Bool    (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part);
+   typedef void         (*GenlistItemDelFunc)      (void *data, Evas_Object *obj);
+
+   struct _Elm_Genlist_Item_Class
+     {
+       const char                *item_style;
+       struct {
+          GenlistItemLabelGetFunc  label_get;
+          GenlistItemIconGetFunc   icon_get;
+          GenlistItemStateGetFunc  state_get;
+          GenlistItemDelFunc       del;
+        } func;
+     };
+
+   EAPI Evas_Object      *elm_genlist_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_multi_select_set(Evas_Object *obj, Eina_Bool multi) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_genlist_multi_select_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_horizontal_mode_set(Evas_Object *obj, Elm_List_Mode mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_List_Mode     elm_genlist_horizontal_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_genlist_always_select_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_genlist_no_select_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_compress_mode_set(Evas_Object *obj, Eina_Bool compress) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_genlist_compress_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_height_for_width_mode_set(Evas_Object *obj, Eina_Bool height_for_width) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_genlist_height_for_width_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         elm_genlist_homogeneous_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_block_count_set(Evas_Object *obj, int n) EINA_ARG_NONNULL(1);
+   EAPI int               elm_genlist_block_count_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_longpress_timeout_set(Evas_Object *obj, double timeout) EINA_ARG_NONNULL(1);
+   EAPI double            elm_genlist_longpress_timeout_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* operations to add items */
+   EAPI Elm_Genlist_Item *elm_genlist_item_append(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Genlist_Item *parent, Elm_Genlist_Item_Flags flags, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Genlist_Item *elm_genlist_item_prepend(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Genlist_Item *parent, Elm_Genlist_Item_Flags flags, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Genlist_Item *elm_genlist_item_insert_before(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Genlist_Item *parent, Elm_Genlist_Item *before, Elm_Genlist_Item_Flags flags, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1, 5);
+   EAPI Elm_Genlist_Item *elm_genlist_item_insert_after(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Genlist_Item *parent, Elm_Genlist_Item *after, Elm_Genlist_Item_Flags flags, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1, 5);
+   /* operations to retrieve existing items */
+   EAPI Elm_Genlist_Item *elm_genlist_selected_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List  *elm_genlist_selected_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_List        *elm_genlist_realized_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Genlist_Item *elm_genlist_at_xy_item_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *posret) EINA_ARG_NONNULL(1);
+   EAPI Elm_Genlist_Item *elm_genlist_first_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Genlist_Item *elm_genlist_last_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) EINA_ARG_NONNULL(1);
+   EAPI void              elm_genlist_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) EINA_ARG_NONNULL(1);
+   /* available item styles:
+    * default
+    * default_style - The text part is a textblock
+    * double_label
+    * icon_top_text_bottom
+    */
+   /* Genlist Item operation */
+   EAPI Elm_Genlist_Item  *elm_genlist_item_next_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Genlist_Item  *elm_genlist_item_prev_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object       *elm_genlist_item_genlist_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Genlist_Item  *elm_genlist_item_parent_get(const Elm_Genlist_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_subitems_clear(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_selected_set(Elm_Genlist_Item *item, Eina_Bool selected) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_genlist_item_selected_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_expanded_set(Elm_Genlist_Item *item, Eina_Bool expanded) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_genlist_item_expanded_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI int                elm_genlist_item_expanded_depth_get(const Elm_Genlist_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_disabled_set(Elm_Genlist_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_genlist_item_disabled_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_display_only_set(Elm_Genlist_Item *it, Eina_Bool display_only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_genlist_item_display_only_get(const Elm_Genlist_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_show(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_bring_in(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_top_show(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_top_bring_in(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_middle_show(Elm_Genlist_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_middle_bring_in(Elm_Genlist_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_del(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void              *elm_genlist_item_data_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_data_set(Elm_Genlist_Item *it, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_icons_orphan(Elm_Genlist_Item *it) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object *elm_genlist_item_object_get(const Elm_Genlist_Item *it) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_update(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_item_class_update(Elm_Genlist_Item *it, const Elm_Genlist_Item_Class *itc) EINA_ARG_NONNULL(1, 2);
+   EAPI void               elm_genlist_item_tooltip_text_set(Elm_Genlist_Item *item, const char *text) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_tooltip_content_cb_set(Elm_Genlist_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_tooltip_unset(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_tooltip_style_set(Elm_Genlist_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_genlist_item_tooltip_style_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_cursor_set(Elm_Genlist_Item *item, const char *cursor) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_genlist_item_cursor_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_cursor_unset(Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_cursor_style_set(Elm_Genlist_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char        *elm_genlist_item_cursor_style_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               elm_genlist_item_cursor_engine_only_set(Elm_Genlist_Item *item, Eina_Bool engine_only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_genlist_item_cursor_engine_only_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1);
+
+   /* check */
+   EAPI Evas_Object *elm_check_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_check_label_set(Evas_Object *obj, const char *label); EINA_ARG_NONNULL(1)
+   EAPI const char  *elm_check_label_get(const Evas_Object *obj); EINA_ARG_NONNULL(1)
+   EAPI void         elm_check_icon_set(Evas_Object *obj, Evas_Object *icon); EINA_ARG_NONNULL(1)
+   EAPI Evas_Object *elm_check_icon_get(const Evas_Object *obj); EINA_ARG_NONNULL(1)
+   EAPI Evas_Object *elm_check_icon_unset(Evas_Object *obj); EINA_ARG_NONNULL(1)
+   EAPI void         elm_check_state_set(Evas_Object *obj, Eina_Bool state); EINA_ARG_NONNULL(1)
+   EAPI Eina_Bool    elm_check_state_get(const Evas_Object *obj); EINA_ARG_NONNULL(1)
+   EAPI void         elm_check_state_pointer_set(Evas_Object *obj, Eina_Bool *statep); EINA_ARG_NONNULL(1)
+
+   /* radio */
+   EAPI Evas_Object *elm_radio_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_radio_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_radio_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_radio_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_radio_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_radio_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_radio_group_add(Evas_Object *obj, Evas_Object *group) EINA_ARG_NONNULL(1);
+   EAPI void         elm_radio_state_value_set(Evas_Object *obj, int value) EINA_ARG_NONNULL(1);
+   EAPI int          elm_radio_state_value_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_radio_value_set(Evas_Object *obj, int value) EINA_ARG_NONNULL(1);
+   EAPI int          elm_radio_value_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_radio_value_pointer_set(Evas_Object *obj, int *valuep) EINA_ARG_NONNULL(1);
+
+   /* pager */
+   EAPI Evas_Object *elm_pager_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_pager_content_push(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI void         elm_pager_content_pop(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_pager_content_promote(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_pager_content_bottom_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_pager_content_top_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* available item styles:
+    * default
+    * fade
+    * fade_translucide
+    * fade_invisible
+    */
+
+   typedef struct _Elm_Slideshow_Item_Class Elm_Slideshow_Item_Class;
+   typedef struct _Elm_Slideshow_Item_Class_Func Elm_Slideshow_Item_Class_Func;
+   typedef struct _Elm_Slideshow_Item       Elm_Slideshow_Item; /**< Item of Elm_Slideshow. Sub-type of Elm_Widget_Item */
+   typedef Evas_Object *(*SlideshowItemGetFunc) (void *data, Evas_Object *obj);
+   typedef void         (*SlideshowItemDelFunc) (void *data, Evas_Object *obj);
+
+   struct _Elm_Slideshow_Item_Class
+     {
+       struct _Elm_Slideshow_Item_Class_Func {
+          SlideshowItemGetFunc get;
+          SlideshowItemDelFunc del;
+       } func;
+     };
+
+   EAPI Evas_Object        *elm_slideshow_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Elm_Slideshow_Item *elm_slideshow_item_add(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_show(Elm_Slideshow_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_next(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_previous(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List    *elm_slideshow_transitions_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_transition_set(Evas_Object *obj, const char *transition) EINA_ARG_NONNULL(1);
+   EAPI const char         *elm_slideshow_transition_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_timeout_set(Evas_Object *obj, double timeout) EINA_ARG_NONNULL(1);
+   EAPI double              elm_slideshow_timeout_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_loop_set(Evas_Object *obj, Eina_Bool loop) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool           elm_slideshow_loop_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List    *elm_slideshow_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_item_del(Elm_Slideshow_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void               *elm_slideshow_item_data_get(const Elm_Slideshow_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Slideshow_Item *elm_slideshow_item_current_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object*        elm_slideshow_item_object_get(const Elm_Slideshow_Item* item) EINA_ARG_NONNULL(1);
+   EAPI const char         *elm_slideshow_layout_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                elm_slideshow_layout_set(Evas_Object *obj, const char *layout) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List    *elm_slideshow_layouts_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "changed" - when the slideshow switch to another item
+    */
+
+   /* file selector */
+   typedef enum _Elm_Fileselector_Mode
+     {
+        ELM_FILESELECTOR_LIST = 0,
+        ELM_FILESELECTOR_GRID,
+        ELM_FILESELECTOR_LAST
+     } Elm_Fileselector_Mode;
+
+   EAPI Evas_Object          *elm_fileselector_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_fileselector_is_save_set(Evas_Object *obj, Eina_Bool is_save) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_fileselector_is_save_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_fileselector_folder_only_set(Evas_Object *obj, Eina_Bool only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_fileselector_folder_only_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj, Eina_Bool buttons) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_fileselector_buttons_ok_cancel_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_fileselector_expandable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_fileselector_expandable_set(Evas_Object *obj, Eina_Bool expand) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_fileselector_path_set(Evas_Object *obj, const char *path) EINA_ARG_NONNULL(1);
+   EAPI const char           *elm_fileselector_path_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const char           *elm_fileselector_selected_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_fileselector_selected_set(Evas_Object *obj, const char *path) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_fileselector_mode_set(Evas_Object *obj, Elm_Fileselector_Mode mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_Fileselector_Mode elm_fileselector_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "selected" - the user click on a file
+    * "directory,open" - the list is populate with a new content. event_info is a directory.
+    * "done" - the user click on the ok or cancel buttons
+    */
+
+   /* progressbar */
+   EAPI Evas_Object *elm_progressbar_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_pulse_set(Evas_Object *obj, Eina_Bool pulse) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_progressbar_pulse_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_pulse(Evas_Object *obj, Eina_Bool state) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_value_set(Evas_Object *obj, double val) EINA_ARG_NONNULL(1);
+   EAPI double       elm_progressbar_value_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_label_set(Evas_Object *obj, const char *label) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_progressbar_label_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_progressbar_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_progressbar_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_span_size_set(Evas_Object *obj, Evas_Coord size) EINA_ARG_NONNULL(1);
+   EAPI Evas_Coord   elm_progressbar_span_size_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_unit_format_set(Evas_Object *obj, const char *format) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_progressbar_unit_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_progressbar_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_progressbar_inverted_set(Evas_Object *obj, Eina_Bool inverted) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_progressbar_inverted_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    */
+   /* available item styles:
+    * default
+    * wheel (simple style, no text, no progression, only pulse is available)
+    */
+
+   /* separator */
+   EAPI Evas_Object *elm_separator_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_separator_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_separator_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    */
+
+   /* spinner */
+   EAPI Evas_Object *elm_spinner_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_label_format_set(Evas_Object *obj, const char *fmt) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_spinner_label_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_min_max_set(Evas_Object *obj, double min, double max) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_min_max_get(const Evas_Object *obj, double *min, double *max) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_step_set(Evas_Object *obj, double step) EINA_ARG_NONNULL(1);
+   EAPI double       elm_spinner_step_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_value_set(Evas_Object *obj, double val) EINA_ARG_NONNULL(1);
+   EAPI double       elm_spinner_value_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_wrap_set(Evas_Object *obj, Eina_Bool wrap) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_spinner_wrap_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_editable_set(Evas_Object *obj, Eina_Bool editable) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_spinner_editable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_special_value_add(Evas_Object *obj, double value, const char *label) EINA_ARG_NONNULL(1);
+   EAPI void         elm_spinner_interval_set(Evas_Object *obj, double interval) EINA_ARG_NONNULL(1);
+   EAPI double       elm_spinner_interval_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "changed" - when the spinner value changes
+    * "delay,changed" - when the spinner value changed, but a small time after a change (use this if you only want to respond to a change once the spinner is held still for a short while).
+    */
+   /* available item styles:
+    * default
+    * vertical (two up/down buttons at the right side and text left aligned)
+    */
+
+   /* index */
+   typedef struct _Elm_Index_Item Elm_Index_Item; /**< Item of Elm_Index. Sub-type of Elm_Widget_Item */
+
+   EAPI Evas_Object    *elm_index_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_active_set(Evas_Object *obj, Eina_Bool active) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_level_set(Evas_Object *obj, int level) EINA_ARG_NONNULL(1);
+   EAPI int             elm_index_item_level_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void           *elm_index_item_selected_get(const Evas_Object *obj, int level) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_append(Evas_Object *obj, const char *letter, const void *item) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, const void *item, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_del(Evas_Object *obj, const void *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Index_Item *elm_index_item_find(Evas_Object *obj, const void *item) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_go(Evas_Object *obj, int level) EINA_ARG_NONNULL(1);
+   EAPI void           *elm_index_item_data_get(const Elm_Index_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_data_set(Elm_Index_Item *it, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void            elm_index_item_del_cb_set(Elm_Index_Item *it, Evas_Smart_Cb func) EINA_ARG_NONNULL(1);
+   EAPI const char     *elm_index_item_letter_get(const Elm_Index_Item *item) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "changed" - when the selected index item changes
+    * "delay,changed" - when the selected index item changes, but after some small idle period
+    * "selected" - when the user releases a finger and selects an item
+    * "level,up" - when the user moves a finger from the first level to the second level
+    * "level,down" - when the user moves a finger from the second level to the first level
+    */
+
+   /* photocam */
+   typedef enum _Elm_Photocam_Zoom_Mode
+     {
+        ELM_PHOTOCAM_ZOOM_MODE_MANUAL = 0,
+        ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT,
+        ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL,
+        ELM_PHOTOCAM_ZOOM_MODE_LAST
+     } Elm_Photocam_Zoom_Mode;
+
+   EAPI Evas_Object           *elm_photocam_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Load_Error        elm_photocam_file_set(Evas_Object *obj, const char *file) EINA_ARG_NONNULL(1);
+   EAPI const char            *elm_photocam_file_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_zoom_set(Evas_Object *obj, double zoom) EINA_ARG_NONNULL(1);
+   EAPI double                 elm_photocam_zoom_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_zoom_mode_set(Evas_Object *obj, Elm_Photocam_Zoom_Mode mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_Photocam_Zoom_Mode elm_photocam_zoom_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_image_size_get(const Evas_Object *obj, int *w, int *h) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_image_region_show(Evas_Object *obj, int x, int y, int w, int h) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_image_region_bring_in(Evas_Object *obj, int x, int y, int w, int h) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_paused_set(Evas_Object *obj, Eina_Bool paused) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool              elm_photocam_paused_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object           *elm_photocam_internal_image_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_bounce_set(Evas_Object *obj,  Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_photocam_bounce_get(const Evas_Object *obj,  Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "clicked" - when image clicked
+    * "press" - when mouse/finger held down initially on image
+    * "longpressed" - when mouse/finger held for long time on image
+    * "clicked,double" - when mouse/finger double-clicked
+    * "load" - when photo load begins
+    * "loaded" - when photo load done
+    * "load,details" - when detailed image load begins
+    * "loaded,details" - when detailed image load done
+    * "zoom,start" - when zooming started
+    * "zoom,stop" - when zooming stopped
+    * "zoom,change" - when auto zoom mode changed zoom level
+    * "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
+    */
+
+   /* map */
+   typedef enum _Elm_Map_Zoom_Mode
+     {
+        ELM_MAP_ZOOM_MODE_MANUAL,
+        ELM_MAP_ZOOM_MODE_AUTO_FIT,
+        ELM_MAP_ZOOM_MODE_AUTO_FILL,
+        ELM_MAP_ZOOM_MODE_LAST
+     } Elm_Map_Zoom_Mode;
+
+   typedef enum _Elm_Map_Sources
+     {
+        ELM_MAP_SOURCE_MAPNIK,
+        ELM_MAP_SOURCE_OSMARENDER,
+        ELM_MAP_SOURCE_CYCLEMAP,
+        ELM_MAP_SOURCE_MAPLINT,
+        ELM_MAP_SOURCE_CUSTOM_1,
+        ELM_MAP_SOURCE_CUSTOM_2,
+        ELM_MAP_SOURCE_CUSTOM_3,
+        ELM_MAP_SOURCE_CUSTOM_4,
+        ELM_MAP_SOURCE_CUSTOM_5,
+        ELM_MAP_SOURCE_CUSTOM_6,
+        ELM_MAP_SOURCE_MODULE,
+        ELM_MAP_SOURCE_LAST
+     } Elm_Map_Sources;
+
+   typedef struct _Elm_Map_Marker       Elm_Map_Marker;
+   typedef struct _Elm_Map_Marker_Class Elm_Map_Marker_Class;
+   typedef struct _Elm_Map_Group_Class  Elm_Map_Group_Class;
+   typedef Evas_Object *(*ElmMapMarkerGetFunc)      (Evas_Object *obj, Elm_Map_Marker *marker, void *data);
+   typedef void         (*ElmMapMarkerDelFunc)      (Evas_Object *obj, Elm_Map_Marker *marker, void *data, Evas_Object *o);
+   typedef Evas_Object *(*ElmMapMarkerIconGetFunc)  (Evas_Object *obj, Elm_Map_Marker *marker, void *data);
+   typedef Evas_Object *(*ElmMapGroupIconGetFunc)   (Evas_Object *obj, void *data);
+   typedef char        *(*ElmMapSourceURLFunc)      (Evas_Object *obj, int x, int y, int zoom);
+
+   EAPI Evas_Object          *elm_map_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_zoom_set(Evas_Object *obj, int zoom) EINA_ARG_NONNULL(1);
+   EAPI double                elm_map_zoom_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_Mode mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_Map_Zoom_Mode     elm_map_zoom_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_geo_region_get(const Evas_Object *obj, double *lon, double *lat) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_geo_region_bring_in(Evas_Object *obj, double lon, double lat) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_geo_region_show(Evas_Object *obj, double lon, double lat) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_paused_set(Evas_Object *obj, Eina_Bool paused) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_map_paused_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_paused_markers_set(Evas_Object *obj, Eina_Bool paused) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_map_paused_markers_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_utils_downloading_status_get(const Evas_Object *obj, int *try_num, int *finish_num) EINA_ARG_NONNULL(1, 2, 3);
+   EAPI void                 elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int size, double *lon, double *lat);
+   EAPI void                  elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double lat, int size, int *x, int *y);
+   EAPI Elm_Map_Marker       *elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *clas_group, void *data) EINA_ARG_NONNULL(1, 4, 5);
+   EAPI void                  elm_map_max_marker_per_group_set(Evas_Object *obj, int max) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_remove(Elm_Map_Marker *marker) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_bring_in(Elm_Map_Marker *marker) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_show(Elm_Map_Marker *marker) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_markers_list_show(Eina_List *markers) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_map_marker_object_get(const Elm_Map_Marker *marker) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_update(Elm_Map_Marker *marker) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_bubbles_close(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Map_Group_Class  *elm_map_group_class_new(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_group_class_style_set(Elm_Map_Group_Class *clas, const char *style) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, ElmMapGroupIconGetFunc icon_get) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_group_class_data_set(Elm_Map_Group_Class *clas, void *data) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_group_class_zoom_displayed_set(Elm_Map_Group_Class *clas, int zoom) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_group_class_zoom_grouped_set(Elm_Map_Group_Class *clas, int zoom) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_group_class_hide_set(Evas_Object *obj, Elm_Map_Group_Class *clas, Eina_Bool hide) EINA_ARG_NONNULL(1, 2);
+   EAPI Elm_Map_Marker_Class *elm_map_marker_class_new(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_class_style_set(Elm_Map_Marker_Class *clas, const char *style) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerIconGetFunc icon_get) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerGetFunc get) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerDelFunc del) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_source_set(Evas_Object *obj, Elm_Map_Sources source) EINA_ARG_NONNULL(1);
+   EAPI Elm_Map_Sources       elm_map_source_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_source_custom_api_set(Elm_Map_Sources source, const char *label, int zoom_min, int zoom_max, ElmMapSourceURLFunc url_cb) EINA_ARG_NONNULL(2, 5);
+   EAPI int                   elm_map_source_zoom_min_get(Elm_Map_Sources source);
+   EAPI int                   elm_map_source_zoom_max_get(Elm_Map_Sources source);
+   EAPI const char           *elm_map_source_name_get(Elm_Map_Sources source);
+   /* smart callbacks called:
+    * "clicked" - when image clicked
+    * "press" - when mouse/finger held down initially on image
+    * "longpressed" - when mouse/finger held for long time on image
+    * "clicked,double" - when mouse/finger double-clicked
+    * "load,details" - when detailed image load begins
+    * "loaded,details" - when detailed image load done
+    * "zoom,start" - when zooming started
+    * "zoom,stop" - when zooming stopped
+    * "zoom,change" - when auto zoom mode changed zoom level
+    * "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
+    */
+
+   /* panel */
+   typedef enum _Elm_Panel_Orient
+     {
+        ELM_PANEL_ORIENT_TOP,
+        ELM_PANEL_ORIENT_BOTTOM,
+        ELM_PANEL_ORIENT_LEFT,
+        ELM_PANEL_ORIENT_RIGHT,
+     } Elm_Panel_Orient;
+
+   EAPI Evas_Object          *elm_panel_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panel_orient_set(Evas_Object *obj, Elm_Panel_Orient orient) EINA_ARG_NONNULL(1);
+   EAPI Elm_Panel_Orient      elm_panel_orient_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panel_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_panel_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_panel_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_panel_hidden_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panel_toggle(Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* panes */
+   /**
+    * TODO
+    *
+    * Update the minimun height of the bar in the theme. No minimun should be set in the vertical theme
+    * Add events (move, start ...)
+    */
+   EAPI Evas_Object          *elm_panes_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panes_content_left_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panes_content_right_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_panes_content_left_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_panes_content_right_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_panes_content_left_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object          *elm_panes_content_right_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI double                elm_panes_content_left_size_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panes_content_left_size_set(Evas_Object *obj, double size) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_panes_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool             elm_panes_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* flip */
+   typedef enum _Elm_Flip_Mode
+     {
+        ELM_FLIP_ROTATE_Y_CENTER_AXIS,
+        ELM_FLIP_ROTATE_X_CENTER_AXIS,
+        ELM_FLIP_ROTATE_XZ_CENTER_AXIS,
+        ELM_FLIP_ROTATE_YZ_CENTER_AXIS,
+        ELM_FLIP_CUBE_LEFT,
+        ELM_FLIP_CUBE_RIGHT,
+        ELM_FLIP_CUBE_UP,
+        ELM_FLIP_CUBE_DOWN
+     } Elm_Flip_Mode;
+
+   EAPI Evas_Object *elm_flip_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_flip_content_front_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI void         elm_flip_content_back_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_flip_content_front_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_flip_content_back_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_flip_content_front_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_flip_content_back_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_flip_front_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_flip_perspective_set(Evas_Object *obj, Evas_Coord foc, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1);
+   EAPI void         elm_flip_go(Evas_Object *obj, Elm_Flip_Mode mode) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "animate,done" - when a flip animation is finished
+    */
+
+   /* scrolledentry */
+   EAPI Evas_Object *elm_scrolled_entry_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_single_line_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_password_set(Evas_Object *obj, Eina_Bool password) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_password_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_entry_set(Evas_Object *obj, const char *entry) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_scrolled_entry_entry_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_is_empty(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_scrolled_entry_selection_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_entry_insert(Evas_Object *obj, const char *entry) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_line_wrap_set(Evas_Object *obj, Eina_Bool wrap) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_line_char_wrap_set(Evas_Object *obj, Eina_Bool wrap) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_editable_set(Evas_Object *obj, Eina_Bool editable) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_editable_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_select_none(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_select_all(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_cursor_next(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_cursor_prev(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_cursor_up(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_cursor_down(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_cursor_begin_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_cursor_end_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_cursor_line_begin_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_cursor_line_end_set(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_cursor_selection_begin(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_cursor_selection_end(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_cursor_is_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_cursor_is_visible_format_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const char  *elm_scrolled_entry_cursor_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_selection_cut(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_selection_copy(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_selection_paste(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_context_menu_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_context_menu_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_context_menu_disabled_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_icon_set(Evas_Object *obj, Evas_Object *icon) EINA_ARG_NONNULL(1, 2);
+   EAPI Evas_Object *elm_scrolled_entry_icon_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_scrolled_entry_icon_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_end_set(Evas_Object *obj, Evas_Object *end) EINA_ARG_NONNULL(1, 2);
+   EAPI Evas_Object *elm_scrolled_entry_end_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_scrolled_entry_end_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_scrolled_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_scrolled_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_scrolled_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_scrolled_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_scrolled_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_scrolled_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_file_save(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_scrolled_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_scrolled_entry_autosave_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* conformant */
+   EAPI Evas_Object *elm_conformant_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_conformant_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_conformant_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_conformant_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* mapbuf */
+   EAPI Evas_Object *elm_mapbuf_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_mapbuf_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_mapbuf_content_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object *elm_mapbuf_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_mapbuf_enabled_set(Evas_Object *obj, Eina_Bool enabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_mapbuf_enabled_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_mapbuf_smooth_set(Evas_Object *obj, Eina_Bool smooth) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_mapbuf_smooth_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_mapbuf_alpha_set(Evas_Object *obj, Eina_Bool alpha) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool    elm_mapbuf_alpha_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+   /* flipselector */
+   typedef struct _Elm_Flipselector_Item Elm_Flipselector_Item;
+
+   EAPI Evas_Object               *elm_flipselector_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void                       elm_flipselector_flip_next(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                       elm_flipselector_flip_prev(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Flipselector_Item     *elm_flipselector_item_append(Evas_Object *obj, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), void *data) EINA_ARG_NONNULL(1);
+   EAPI Elm_Flipselector_Item     *elm_flipselector_item_prepend(Evas_Object *obj, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), void *data) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List           *elm_flipselector_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Flipselector_Item     *elm_flipselector_first_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Flipselector_Item     *elm_flipselector_last_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Flipselector_Item     *elm_flipselector_selected_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                       elm_flipselector_item_selected_set(Elm_Flipselector_Item *item, Eina_Bool selected) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                  elm_flipselector_item_selected_get(const Elm_Flipselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                       elm_flipselector_item_del(Elm_Flipselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI const char                *elm_flipselector_item_label_get(const Elm_Flipselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                       elm_flipselector_item_label_set(Elm_Flipselector_Item *item, const char *label) EINA_ARG_NONNULL(1);
+   EAPI Elm_Flipselector_Item     *elm_flipselector_item_prev_get(Elm_Flipselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Flipselector_Item     *elm_flipselector_item_next_get(Elm_Flipselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                       elm_flipselector_interval_set(Evas_Object *obj, double interval) EINA_ARG_NONNULL(1);
+   EAPI double                     elm_flipselector_interval_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "selected" - when flipselector selected item is changed
+    * "overflowed" - when flipselector item is changed to first item
+    *                from last item
+    * "underflowed" - when flipselector item is changed to last item
+    *                 from first item.
+    */
+   /* available styles:
+    * default
+    */
+
+   /* animator */
+   typedef enum
+     {
+        ELM_ANIMATOR_CURVE_LINEAR,
+        ELM_ANIMATOR_CURVE_IN_OUT,
+        ELM_ANIMATOR_CURVE_IN,
+        ELM_ANIMATOR_CURVE_OUT
+     } Elm_Animator_Curve_Style;
+   typedef struct _Elm_Animator Elm_Animator;
+  /**
+   * Called back per loop of an elementary animators cycle
+   * @param data user-data given to elm_animator_operation_callback_set()
+   * @param animator the animator being run
+   * @param double the position in the animation
+   */
+   typedef void (*Elm_Animator_Operation_Cb) (void *data, Elm_Animator *animator, double frame);
+  /**
+   * Called back when an elementary animator finishes
+   * @param data user-data given to elm_animator_completion_callback_set()
+   */
+   typedef void (*Elm_Animator_Completion_Cb) (void *data);
+
+   EAPI Elm_Animator*            elm_animator_add(Evas_Object *parent);
+   EAPI void                     elm_animator_del(Elm_Animator *animator) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_duration_set(Elm_Animator *animator, double duration) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_operation_callback_set(Elm_Animator *animator, Elm_Animator_Operation_Cb func, void *data) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_completion_callback_set(Elm_Animator *animator, Elm_Animator_Completion_Cb func, void *data) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_stop(Elm_Animator *animator) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_animate(Elm_Animator *animator) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_curve_style_set(Elm_Animator *animator, Elm_Animator_Curve_Style cs) EINA_ARG_NONNULL(1);
+   EAPI Elm_Animator_Curve_Style elm_animator_curve_style_get(const Elm_Animator *animator); EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                elm_animator_auto_reverse_get(const Elm_Animator *animator) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                elm_animator_operating_get(const Elm_Animator *animator) EINA_ARG_NONNULL(1);
+   EAPI unsigned int             elm_animator_repeat_get(const Elm_Animator *animator) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_pause(Elm_Animator *animator) EINA_ARG_NONNULL(1);
+   EAPI void                     elm_animator_resume(Elm_Animator *animator) EINA_ARG_NONNULL(1);
+
+   /* calendar */
+   typedef enum
+     {
+        ELM_CALENDAR_UNIQUE,
+        ELM_CALENDAR_DAILY,
+        ELM_CALENDAR_WEEKLY,
+        ELM_CALENDAR_MONTHLY,
+        ELM_CALENDAR_ANNUALLY
+     } Elm_Calendar_Mark_Repeat;
+   typedef struct _Elm_Calendar_Mark Elm_Calendar_Mark;
+
+   EAPI Evas_Object       *elm_calendar_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI const char       **elm_calendar_weekdays_names_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_weekdays_names_set(Evas_Object *obj, const char *weekdays[]) EINA_ARG_NONNULL(1, 2);
+   EAPI double             elm_calendar_interval_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_interval_set(Evas_Object *obj, double interval) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_min_max_year_get(const Evas_Object *obj, int *min, int *max) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_min_max_year_set(Evas_Object *obj, int min, int max) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_calendar_day_selection_enabled_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_day_selection_enabled_set(Evas_Object *obj, Eina_Bool enabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool          elm_calendar_selected_time_get(const Evas_Object *obj, struct tm *selected_time) EINA_ARG_NONNULL(1, 2);
+   EAPI void               elm_calendar_selected_time_set(Evas_Object *obj, struct tm *selected_time) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_format_function_set(Evas_Object *obj, char * (*format_function) (struct tm *stime)) EINA_ARG_NONNULL(1);
+   EAPI Elm_Calendar_Mark *elm_calendar_mark_add(Evas_Object *obj, const char *mark_type, struct tm *mark_time, Elm_Calendar_Mark_Repeat repeat) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_mark_del(Elm_Calendar_Mark *mark) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_marks_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List   *elm_calendar_marks_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_calendar_marks_draw(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EINA_DEPRECATED EAPI void               elm_calendar_text_saturday_color_set(Evas_Object *obj, int pos) EINA_ARG_NONNULL(1);
+   EINA_DEPRECATED EAPI void               elm_calendar_text_sunday_color_set(Evas_Object *obj, int pos) EINA_ARG_NONNULL(1);
+   EINA_DEPRECATED EAPI void               elm_calendar_text_weekday_color_set(Evas_Object *obj, int pos) EINA_ARG_NONNULL(1);
+
+   /* smart callbacks called:
+    * changed - emitted when the user select a day or change the displayed
+    * month.
+    */
+
+   /* diskselector */
+   typedef struct _Elm_Diskselector_Item Elm_Diskselector_Item;
+
+   EAPI Evas_Object           *elm_diskselector_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool              elm_diskselector_round_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_round_set(Evas_Object *obj, Eina_Bool round) EINA_ARG_NONNULL(1);
+   EAPI int                    elm_diskselector_side_label_lenght_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_side_label_lenght_set(Evas_Object *obj, int len) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Eina_List       *elm_diskselector_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Diskselector_Item *elm_diskselector_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_diskselector_item_del(Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_del_cb_set(Elm_Diskselector_Item *item, Evas_Smart_Cb func) EINA_ARG_NONNULL(1);
+   EAPI void                  *elm_diskselector_item_data_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object           *elm_diskselector_item_icon_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_icon_set(Elm_Diskselector_Item *item, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI const char            *elm_diskselector_item_label_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_label_set(Elm_Diskselector_Item *item, const char *label) EINA_ARG_NONNULL(1);
+   EAPI Elm_Diskselector_Item *elm_diskselector_selected_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_selected_set(Elm_Diskselector_Item *item, Eina_Bool selected) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool              elm_diskselector_item_selected_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Diskselector_Item *elm_diskselector_first_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Diskselector_Item *elm_diskselector_last_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Diskselector_Item *elm_diskselector_item_prev_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI Elm_Diskselector_Item *elm_diskselector_item_next_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_tooltip_text_set(Elm_Diskselector_Item *item, const char *text) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_tooltip_content_cb_set(Elm_Diskselector_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_tooltip_unset(Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_tooltip_style_set(Elm_Diskselector_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char            *elm_diskselector_item_tooltip_style_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_cursor_set(Elm_Diskselector_Item *item, const char *cursor) EINA_ARG_NONNULL(1);
+   EAPI const char            *elm_diskselector_item_cursor_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_cursor_unset(Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_cursor_style_set(Elm_Diskselector_Item *item, const char *style) EINA_ARG_NONNULL(1);
+   EAPI const char            *elm_diskselector_item_cursor_style_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_diskselector_item_cursor_engine_only_set(Elm_Diskselector_Item *item, Eina_Bool engine_only) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool              elm_diskselector_item_cursor_engine_only_get(const Elm_Diskselector_Item *item) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "selected" - when item is selected (scroller stops)
+    */
+
+   /* colorselector */
+   EAPI Evas_Object *elm_colorselector_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI void         elm_colorselector_color_set(Evas_Object *obj, int r, int g , int b, int a) EINA_ARG_NONNULL(1);
+   EAPI void         elm_colorselector_color_get(const Evas_Object *obj, int *r, int *g , int *b, int *a) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "changed" - when the color value changes
+    */
+
+   /* Contextual Popup */
+   typedef struct _Elm_Ctxpopup_Item Elm_Ctxpopup_Item;
+
+   typedef enum _Elm_Ctxpopup_Direction
+     {
+        ELM_CTXPOPUP_DIRECTION_DOWN,
+        ELM_CTXPOPUP_DIRECTION_RIGHT,
+        ELM_CTXPOPUP_DIRECTION_LEFT,
+        ELM_CTXPOPUP_DIRECTION_UP,
+     } Elm_Ctxpopup_Direction;
+
+   EAPI Evas_Object  *elm_ctxpopup_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
+   EAPI Evas_Object  *elm_ctxpopup_item_icon_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); 
+   EAPI void          elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) EINA_ARG_NONNULL(1);
+   EAPI const char   *elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1);  
+   EAPI void          elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label) EINA_ARG_NONNULL(1);
+   EAPI void          elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1, 2); 
+   EAPI Evas_Object  *elm_ctxpopup_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void          elm_ctxpopup_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void          elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool     elm_ctxpopup_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   Elm_Ctxpopup_Item *elm_ctxpopup_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
+   EAPI void          elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void          elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool     elm_ctxpopup_item_disabled_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1);
+   EAPI void         elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1, 2);
+   EAPI Evas_Object  *elm_ctxpopup_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void         elm_ctxpopup_direction_priority_set(Evas_Object *obj, Elm_Ctxpopup_Direction first, Elm_Ctxpopup_Direction second, Elm_Ctxpopup_Direction third, Elm_Ctxpopup_Direction fourth) EINA_ARG_NONNULL(1);
+   EAPI void         elm_ctxpopup_direction_priority_get(Evas_Object *obj, Elm_Ctxpopup_Direction *first, Elm_Ctxpopup_Direction *second, Elm_Ctxpopup_Direction *third, Elm_Ctxpopup_Direction *fourth) EINA_ARG_NONNULL(1);
+   /* smart callbacks called:
+    * "dismissed" - the ctxpopup was dismissed
+    */
+
+   /* transit */
+   typedef enum
+     {
+        ELM_TRANSIT_TWEEN_MODE_LINEAR,
+        ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL,
+        ELM_TRANSIT_TWEEN_MODE_DECELERATE,
+        ELM_TRANSIT_TWEEN_MODE_ACCELERATE
+     } Elm_Transit_Tween_Mode;
+   typedef enum
+     {
+        ELM_TRANSIT_EFFECT_FLIP_AXIS_X,
+        ELM_TRANSIT_EFFECT_FLIP_AXIS_Y
+     } Elm_Transit_Effect_Flip_Axis;
+   typedef enum
+     {
+        ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT,
+        ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT,
+        ELM_TRANSIT_EFFECT_WIPE_DIR_UP,
+        ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN
+     } Elm_Transit_Effect_Wipe_Dir;
+   typedef enum
+     {
+        ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE,
+        ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW
+     } Elm_Transit_Effect_Wipe_Type;
+
+   typedef struct _Elm_Transit Elm_Transit;
+
+   EAPI Elm_Transit           *elm_transit_add(void);
+   EAPI void                   elm_transit_del(Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_effect_add(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit *transit, double progress), void *data, void (*data_free_cb)(void *data, Elm_Transit *transit)) EINA_ARG_NONNULL(1, 2);
+   EAPI void                   elm_transit_effect_del(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit *transit, double progress), void *data) EINA_ARG_NONNULL(1, 2);
+   EAPI void                   elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj) EINA_ARG_NONNULL(1, 2);
+   EAPI void                   elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj) EINA_ARG_NONNULL(1, 2);
+   EAPI const Eina_List       *elm_transit_objects_get(const Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EINA_DEPRECATED EAPI void                   elm_transit_event_block_set(Elm_Transit *transit, Eina_Bool disabled) EINA_ARG_NONNULL(1);
+   EINA_DEPRECATED EAPI Eina_Bool              elm_transit_event_block_get(const Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool              elm_transit_event_enabled_get(const Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_del_cb_set(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit* transit), void *data) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool              elm_transit_auto_reverse_get(Elm_Transit *transit) EINA_ARG_NONNULL(1) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_repeat_times_set(Elm_Transit *transit, int repeat) EINA_ARG_NONNULL(1);
+   EAPI int                    elm_transit_repeat_times_get(Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode) EINA_ARG_NONNULL(1);
+   EAPI Elm_Transit_Tween_Mode elm_transit_tween_mode_get(const Elm_Transit *transit) EINA_ARG_NONNULL(1) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_duration_set(Elm_Transit *transit, double duration) EINA_ARG_NONNULL(1); 
+   EAPI double                 elm_transit_duration_get(const Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_go(Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EAPI void                   elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool              elm_transit_paused_get(const Elm_Transit *transit) EINA_ARG_NONNULL(1);
+   EAPI double                 elm_transit_progress_value_get(const Elm_Transit *transit) EINA_ARG_NONNULL(1);
+
+   EAPI void                  *elm_transit_effect_resizing_add(Elm_Transit* transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h);
+   EAPI void                  *elm_transit_effect_translation_add(Elm_Transit* transit, Evas_Coord from_dx, Evas_Coord dy, Evas_Coord to_dx, Evas_Coord to_dy);
+   EAPI void                  *elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate);
+   EAPI void                  *elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw);
+   EAPI void                  *elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw);
+   EAPI void                  *elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir);
+   EAPI void                  *elm_transit_effect_color_add(Elm_Transit *transit, unsigned int from_r, unsigned int from_g, unsigned int from_b, unsigned int from_a, unsigned int to_r, unsigned int to_g, unsigned int to_b, unsigned int to_a);
+   EAPI void                  *elm_transit_effect_fade_add(Elm_Transit *transit);
+   EAPI void                  *elm_transit_effect_blend_add(Elm_Transit *transit);
+   EAPI void                  *elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree);
+   EAPI void                  *elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images);       
+
+  typedef struct _Elm_Store                      Elm_Store;
+  typedef struct _Elm_Store_Filesystem           Elm_Store_Filesystem;
+  typedef struct _Elm_Store_Item                 Elm_Store_Item;
+  typedef struct _Elm_Store_Item_Filesystem      Elm_Store_Item_Filesystem;
+  typedef struct _Elm_Store_Item_Info            Elm_Store_Item_Info;
+  typedef struct _Elm_Store_Item_Info_Filesystem Elm_Store_Item_Info_Filesystem;
+  typedef struct _Elm_Store_Item_Mapping         Elm_Store_Item_Mapping;
+  typedef struct _Elm_Store_Item_Mapping_Empty   Elm_Store_Item_Mapping_Empty;
+  typedef struct _Elm_Store_Item_Mapping_Icon    Elm_Store_Item_Mapping_Icon;
+  typedef struct _Elm_Store_Item_Mapping_Photo   Elm_Store_Item_Mapping_Photo;
+  typedef struct _Elm_Store_Item_Mapping_Custom  Elm_Store_Item_Mapping_Custom;
+
+  typedef Eina_Bool (*Elm_Store_Item_List_Cb) (void *data, Elm_Store_Item_Info *info);
+  typedef void      (*Elm_Store_Item_Fetch_Cb) (void *data, Elm_Store_Item *sti);
+  typedef void      (*Elm_Store_Item_Unfetch_Cb) (void *data, Elm_Store_Item *sti);
+  typedef void     *(*Elm_Store_Item_Mapping_Cb) (void *data, Elm_Store_Item *sti, const char *part);
+
+  typedef enum
+    {
+      ELM_STORE_ITEM_MAPPING_NONE = 0,
+      ELM_STORE_ITEM_MAPPING_LABEL, // const char * -> label
+      ELM_STORE_ITEM_MAPPING_STATE, // Eina_Bool -> state
+      ELM_STORE_ITEM_MAPPING_ICON, // char * -> icon path
+      ELM_STORE_ITEM_MAPPING_PHOTO, // char * -> photo path
+      ELM_STORE_ITEM_MAPPING_CUSTOM, // item->custom(it->data, it, part) -> void * (-> any)
+      // can add more here as needed by common apps
+      ELM_STORE_ITEM_MAPPING_LAST
+    } Elm_Store_Item_Mapping_Type;
+
+  struct _Elm_Store_Item_Mapping_Icon
+    {
+      // FIXME: allow edje file icons
+      int                   w, h;
+      Elm_Icon_Lookup_Order lookup_order;
+      Eina_Bool             standard_name : 1;
+      Eina_Bool             no_scale : 1;
+      Eina_Bool             smooth : 1;
+      Eina_Bool             scale_up : 1;
+      Eina_Bool             scale_down : 1;
+    };
+
+  struct _Elm_Store_Item_Mapping_Empty
+    {
+      Eina_Bool             dummy;
+    };
+
+  struct _Elm_Store_Item_Mapping_Photo
+    {
+      int                   size;
+    };
+
+  struct _Elm_Store_Item_Mapping_Custom
+    {
+      Elm_Store_Item_Mapping_Cb func;
+    };
+
+  struct _Elm_Store_Item_Mapping
+    {
+      Elm_Store_Item_Mapping_Type     type;
+      const char                     *part;
+      int                             offset;
+      union {
+        Elm_Store_Item_Mapping_Empty  empty;
+        Elm_Store_Item_Mapping_Icon   icon;
+        Elm_Store_Item_Mapping_Photo  photo;
+        Elm_Store_Item_Mapping_Custom custom;
+        // add more types here
+      } details;
+    };
+
+  struct _Elm_Store_Item_Info
+    {
+      Elm_Genlist_Item_Class       *item_class;
+      const Elm_Store_Item_Mapping *mapping;
+      void                         *data;
+      char                         *sort_id;
+    };
+
+  struct _Elm_Store_Item_Info_Filesystem
+    {
+      Elm_Store_Item_Info  base;
+      char                *path;
+    };
+
+#define ELM_STORE_ITEM_MAPPING_END { ELM_STORE_ITEM_MAPPING_NONE, NULL, 0, { .empty = { EINA_TRUE } } }
+#define ELM_STORE_ITEM_MAPPING_OFFSET(st, it) offsetof(st, it)
+
+  EAPI void                    elm_store_free(Elm_Store *st);
+
+  EAPI Elm_Store              *elm_store_filesystem_new(void);
+  EAPI void                    elm_store_filesystem_directory_set(Elm_Store *st, const char *dir) EINA_ARG_NONNULL(1);
+  EAPI const char             *elm_store_filesystem_directory_get(const Elm_Store *st) EINA_ARG_NONNULL(1);
+  EAPI const char             *elm_store_item_filesystem_path_get(const Elm_Store_Item *sti) EINA_ARG_NONNULL(1);
+
+  EAPI void                    elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+  EAPI void                    elm_store_cache_set(Elm_Store *st, int max) EINA_ARG_NONNULL(1);
+  EAPI int                     elm_store_cache_get(const Elm_Store *st) EINA_ARG_NONNULL(1);
+  EAPI void                    elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data) EINA_ARG_NONNULL(1, 2);
+  EAPI void                    elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data) EINA_ARG_NONNULL(1, 2);
+  EAPI void                    elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread) EINA_ARG_NONNULL(1);
+  EAPI Eina_Bool               elm_store_fetch_thread_get(const Elm_Store *st) EINA_ARG_NONNULL(1);
+
+  EAPI void                    elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data) EINA_ARG_NONNULL(1, 2);
+  EAPI void                    elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted) EINA_ARG_NONNULL(1);
+  EAPI Eina_Bool               elm_store_sorted_get(const Elm_Store *st) EINA_ARG_NONNULL(1);
+  EAPI void                    elm_store_item_data_set(Elm_Store_Item *sti, void *data) EINA_ARG_NONNULL(1);
+  EAPI void                   *elm_store_item_data_get(Elm_Store_Item *sti) EINA_ARG_NONNULL(1);
+  EAPI const Elm_Store        *elm_store_item_store_get(const Elm_Store_Item *sti) EINA_ARG_NONNULL(1);
+  EAPI const Elm_Genlist_Item *elm_store_item_genlist_item_get(const Elm_Store_Item *sti) EINA_ARG_NONNULL(1);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/Elementary_Cursor.h b/src/lib/Elementary_Cursor.h
new file mode 100644 (file)
index 0000000..78a7c40
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef _ELM_CURSOR_H
+#define _ELM_CURSOR_H
+
+/**
+ * @file
+ * @brief Defines the various cursor types for the X Windows system.
+ */
+
+#define ELM_CURSOR_X                   "x"
+#define ELM_CURSOR_ARROW               "arrow"
+#define ELM_CURSOR_BASED_ARROW_DOWN    "based_arrow_down"
+#define ELM_CURSOR_BASED_ARROW_UP      "based_arrow_up"
+#define ELM_CURSOR_BOAT                "boat"
+#define ELM_CURSOR_BOGOSITY            "bogosity"
+#define ELM_CURSOR_BOTTOM_LEFT_CORNER  "bottom_left_corner"
+#define ELM_CURSOR_BOTTOM_RIGHT_CORNER "bottom_right_corner"
+#define ELM_CURSOR_BOTTOM_SIDE         "bottom_side"
+#define ELM_CURSOR_BOTTOM_TEE          "bottom_tee"
+#define ELM_CURSOR_BOX_SPIRAL          "box_spiral"
+#define ELM_CURSOR_CENTER_PTR          "center_ptr"
+#define ELM_CURSOR_CIRCLE              "circle"
+#define ELM_CURSOR_CLOCK               "clock"
+#define ELM_CURSOR_COFFEE_MUG          "coffee_mug"
+#define ELM_CURSOR_CROSS               "cross"
+#define ELM_CURSOR_CROSS_REVERSE       "cross_reverse"
+#define ELM_CURSOR_CROSSHAIR           "crosshair"
+#define ELM_CURSOR_DIAMOND_CROSS       "diamond_cross"
+#define ELM_CURSOR_DOT                 "dot"
+#define ELM_CURSOR_DOT_BOX_MASK        "dot_box_mask"
+#define ELM_CURSOR_DOUBLE_ARROW        "double_arrow"
+#define ELM_CURSOR_DRAFT_LARGE         "draft_large"
+#define ELM_CURSOR_DRAFT_SMALL         "draft_small"
+#define ELM_CURSOR_DRAPED_BOX          "draped_box"
+#define ELM_CURSOR_EXCHANGE            "exchange"
+#define ELM_CURSOR_FLEUR               "fleur"
+#define ELM_CURSOR_GOBBLER             "gobbler"
+#define ELM_CURSOR_GUMBY               "gumby"
+#define ELM_CURSOR_HAND1               "hand1"
+#define ELM_CURSOR_HAND2               "hand2"
+#define ELM_CURSOR_HEART               "heart"
+#define ELM_CURSOR_ICON                "icon"
+#define ELM_CURSOR_IRON_CROSS          "iron_cross"
+#define ELM_CURSOR_LEFT_PTR            "left_ptr"
+#define ELM_CURSOR_LEFT_SIDE           "left_side"
+#define ELM_CURSOR_LEFT_TEE            "left_tee"
+#define ELM_CURSOR_LEFTBUTTON          "leftbutton"
+#define ELM_CURSOR_LL_ANGLE            "ll_angle"
+#define ELM_CURSOR_LR_ANGLE            "lr_angle"
+#define ELM_CURSOR_MAN                 "man"
+#define ELM_CURSOR_MIDDLEBUTTON        "middlebutton"
+#define ELM_CURSOR_MOUSE               "mouse"
+#define ELM_CURSOR_PENCIL              "pencil"
+#define ELM_CURSOR_PIRATE              "pirate"
+#define ELM_CURSOR_PLUS                "plus"
+#define ELM_CURSOR_QUESTION_ARROW      "question_arrow"
+#define ELM_CURSOR_RIGHT_PTR           "right_ptr"
+#define ELM_CURSOR_RIGHT_SIDE          "right_side"
+#define ELM_CURSOR_RIGHT_TEE           "right_tee"
+#define ELM_CURSOR_RIGHTBUTTON         "rightbutton"
+#define ELM_CURSOR_RTL_LOGO            "rtl_logo"
+#define ELM_CURSOR_SAILBOAT            "sailboat"
+#define ELM_CURSOR_SB_DOWN_ARROW       "sb_down_arrow"
+#define ELM_CURSOR_SB_H_DOUBLE_ARROW   "sb_h_double_arrow"
+#define ELM_CURSOR_SB_LEFT_ARROW       "sb_left_arrow"
+#define ELM_CURSOR_SB_RIGHT_ARROW      "sb_right_arrow"
+#define ELM_CURSOR_SB_UP_ARROW         "sb_up_arrow"
+#define ELM_CURSOR_SB_V_DOUBLE_ARROW   "sb_v_double_arrow"
+#define ELM_CURSOR_SHUTTLE             "shuttle"
+#define ELM_CURSOR_SIZING              "sizing"
+#define ELM_CURSOR_SPIDER              "spider"
+#define ELM_CURSOR_SPRAYCAN            "spraycan"
+#define ELM_CURSOR_STAR                "star"
+#define ELM_CURSOR_TARGET              "target"
+#define ELM_CURSOR_TCROSS              "tcross"
+#define ELM_CURSOR_TOP_LEFT_ARROW      "top_left_arrow"
+#define ELM_CURSOR_TOP_LEFT_CORNER     "top_left_corner"
+#define ELM_CURSOR_TOP_RIGHT_CORNER    "top_right_corner"
+#define ELM_CURSOR_TOP_SIDE            "top_side"
+#define ELM_CURSOR_TOP_TEE             "top_tee"
+#define ELM_CURSOR_TREK                "trek"
+#define ELM_CURSOR_UL_ANGLE            "ul_angle"
+#define ELM_CURSOR_UMBRELLA            "umbrella"
+#define ELM_CURSOR_UR_ANGLE            "ur_angle"
+#define ELM_CURSOR_WATCH               "watch"
+#define ELM_CURSOR_XTERM               "xterm"
+
+#endif // ifndef _ELM_CURSOR_H
+
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644 (file)
index 0000000..ab9e24a
--- /dev/null
@@ -0,0 +1,137 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-DELM_INTERAL_API_MDFGELQ=1 \
+-I. \
+-I$(top_builddir) \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/lib \
+-I$(top_builddir)/src/lib \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+@ELEMENTARY_CFLAGS@ \
+@ELEMENTARY_X_CFLAGS@ \
+@ELEMENTARY_FB_CFLAGS@ \
+@ELEMENTARY_SDL_CFLAGS@ \
+@ELEMENTARY_WIN32_CFLAGS@ \
+@ELEMENTARY_WINCE_CFLAGS@ \
+@ELEMENTARY_EDBUS_CFLAGS@ \
+@ELEMENTARY_EFREET_CFLAGS@ \
+@ELEMENTARY_ETHUMB_CFLAGS@ \
+@EVIL_CFLAGS@ \
+@EFL_PTHREAD_CFLAGS@
+
+if ELEMENTARY_WINDOWS_BUILD
+AM_CPPFLAGS += -DELEMENTARY_BUILD
+endif
+
+lib_LTLIBRARIES = libelementary.la
+
+includes_HEADERS = \
+Elementary.h \
+Elementary_Cursor.h \
+elm_widget.h
+includesdir = $(includedir)/elementary-@VMAJ@
+
+libelementary_la_SOURCES = \
+elm_priv.h \
+\
+elm_main.c \
+elm_util.c \
+elm_theme.c \
+elm_module.c \
+elm_store.c \
+\
+elm_win.c \
+elm_widget.c \
+elm_bg.c \
+elm_icon.c \
+elm_image.c \
+elm_box.c \
+elm_button.c \
+elm_scroller.c \
+elm_label.c \
+elm_toggle.c \
+elm_frame.c \
+elm_table.c \
+elm_gengrid.c \
+elm_clock.c \
+elm_layout.c \
+elm_hover.c \
+elm_entry.c \
+elm_bubble.c \
+elm_photo.c \
+elm_toolbar.c \
+elm_list.c \
+elm_slider.c \
+elm_actionslider.c \
+elm_genlist.c \
+elm_check.c \
+elm_radio.c \
+elm_pager.c \
+elm_progressbar.c \
+elm_separator.c \
+elm_spinner.c \
+elm_index.c \
+elm_photocam.c \
+elm_notify.c \
+elm_slideshow.c \
+elm_menu.c \
+elm_panel.c \
+elm_panes.c \
+elm_map.c \
+elm_flip.c \
+elm_conform.c \
+elm_mapbuf.c \
+elm_thumb.c \
+elm_config.c \
+elm_font.c \
+elm_animator.c \
+elm_transit.c \
+elm_calendar.c \
+elm_flipselector.c \
+elm_diskselector.c \
+elm_colorselector.c \
+\
+elc_anchorblock.c \
+elc_anchorview.c \
+elc_ctxpopup.c \
+elc_fileselector.c \
+elc_fileselector_button.c \
+elc_fileselector_entry.c \
+elc_hoversel.c \
+elc_scrolled_entry.c \
+\
+els_tooltip.c \
+els_cursor.c \
+els_pan.c \
+els_pan.h \
+els_scroller.c \
+els_scroller.h \
+els_box.c \
+els_box.h \
+els_icon.c \
+els_icon.h \
+\
+elm_cnp_helper.c
+
+
+libelementary_la_CFLAGS =
+libelementary_la_LIBADD = \
+@my_libs@ \
+@dlopen_libs@ \
+@ELEMENTARY_LIBS@ \
+@ELEMENTARY_X_LIBS@ \
+@ELEMENTARY_FB_LIBS@ \
+@ELEMENTARY_SDL_LIBS@ \
+@ELEMENTARY_WIN32_LIBS@ \
+@ELEMENTARY_WINCE_LIBS@ \
+@ELEMENTARY_EDBUS_LIBS@ \
+@ELEMENTARY_EFREET_LIBS@ \
+@ELEMENTARY_ETHUMB_LIBS@ \
+@EVIL_LIBS@ \
+@EFL_PTHREAD_LIBS@
+libelementary_la_LDFLAGS = \
+-no-undefined @lt_enable_auto_import@ \
+-version-info @version_info@ @release_info@
diff --git a/src/lib/elc_anchorblock.c b/src/lib/elc_anchorblock.c
new file mode 100644 (file)
index 0000000..7c75062
--- /dev/null
@@ -0,0 +1,461 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Anchorblock Anchorblock
+ *
+ * Anchorblock is for displaying tet that contains markup with anchors like:
+ * \<a href=1234\>something\</\> in it. These will be drawn differently and will
+ * be able to be clicked on by the user to display a popup. This popup then
+ * is intended to contain extra options such as "call", "add to contacts",
+ * "open web page" etc.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * anchor,clicked - anchor called was clicked. event_info is anchor info -
+ * Elm_Entry_Anchorview_Info
+ */
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Elm_Anchorblock_Item_Provider Elm_Anchorblock_Item_Provider;
+
+struct _Widget_Data
+{
+   Evas_Object *entry;
+   Evas_Object *hover_parent;
+   Evas_Object *pop, *hover;
+   Eina_List *item_providers;
+   const char *hover_style;
+};
+
+struct _Elm_Anchorblock_Item_Provider
+{
+   Evas_Object *(*func) (void *data, Evas_Object *anchorblock, const char *item);
+   void *data;
+};
+
+static const char *widtype = NULL;
+
+static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_ANCHOR_CLICKED, ""}, /* TODO: declare the type properly, as data is
+                            * being passed
+                            */
+  {NULL, NULL}
+};
+
+static void _del_pre_hook(Evas_Object *obj);
+static void _del_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 _parent_del(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);
+   if (!wd) return;
+   evas_object_event_callback_del_full(wd->entry, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _changed_size_hints, obj);
+   elm_anchorblock_hover_end(obj);
+   elm_anchorblock_hover_parent_set(obj, NULL);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Anchorblock_Item_Provider *ip;
+   if (!wd) return;
+   if (wd->hover_style) eina_stringshare_del(wd->hover_style);
+   EINA_LIST_FREE(wd->item_providers, ip)
+     {
+        free(ip);
+     }
+   free(wd);
+}
+
+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_min_get(wd->entry, &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__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_hover_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_anchorblock_hover_end(data);
+}
+
+static void
+_anchor_clicked(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Elm_Entry_Anchor_Info *info = event_info;
+   Evas_Object *hover_parent;
+   Elm_Entry_Anchorblock_Info ei;
+   Evas_Coord x, w, y, h, px, py;
+   if (!wd) return;
+   wd->pop = elm_icon_add(obj);
+   evas_object_move(wd->pop, info->x, info->y);
+   evas_object_resize(wd->pop, info->w, info->h);
+   wd->hover = elm_hover_add(obj);
+   if (wd->hover_style)
+     elm_object_style_set(wd->hover, wd->hover_style);
+   hover_parent = wd->hover_parent;
+   if (!hover_parent) hover_parent = obj;
+   elm_hover_parent_set(wd->hover, hover_parent);
+   elm_hover_target_set(wd->hover, wd->pop);
+   ei.name = info->name;
+   ei.button = info->button;
+   ei.hover = wd->hover;
+   ei.anchor.x = info->x;
+   ei.anchor.y = info->y;
+   ei.anchor.w = info->w;
+   ei.anchor.h = info->h;
+   evas_object_geometry_get(hover_parent, &x, &y, &w, &h);
+   ei.hover_parent.x = x;
+   ei.hover_parent.y = y;
+   ei.hover_parent.w = w;
+   ei.hover_parent.h = h;
+   px = info->x + (info->w / 2);
+   py = info->y + (info->h / 2);
+   ei.hover_left = 1;
+   if (px < (x + (w / 3))) ei.hover_left = 0;
+   ei.hover_right = 1;
+   if (px > (x + ((w * 2) / 3))) ei.hover_right = 0;
+   ei.hover_top = 1;
+   if (py < (y + (h / 3))) ei.hover_top = 0;
+   ei.hover_bottom = 1;
+   if (py > (y + ((h * 2) / 3))) ei.hover_bottom = 0;
+   evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, &ei);
+   evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked, data);
+   evas_object_show(wd->hover);
+}
+
+static void
+_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->hover_parent = NULL;
+}
+
+static Evas_Object *
+_item_provider(void *data, Evas_Object *entry __UNUSED__, const char *item)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Eina_List *l;
+   Elm_Anchorblock_Item_Provider *ip;
+
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        Evas_Object *o;
+
+        o = ip->func(ip->data, data, item);
+        if (o) return o;
+     }
+   return NULL;
+}
+
+/**
+ * Add a new Anchorblock object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Anchorblock
+ */
+EAPI Evas_Object *
+elm_anchorblock_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "anchorblock");
+   elm_widget_type_set(obj, "anchorblock");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   elm_widget_del_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+
+   wd->entry = elm_entry_add(parent);
+   elm_entry_item_provider_prepend(wd->entry, _item_provider, obj);
+   elm_widget_resize_object_set(obj, wd->entry);
+   elm_entry_editable_set(wd->entry, 0);
+   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);
+
+   evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                 _changed_size_hints, obj);
+
+   elm_entry_entry_set(wd->entry, "");
+
+   evas_object_smart_callback_add(wd->entry, "anchor,clicked",
+                                 _anchor_clicked, obj);
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the text markup of the anchorblock
+ *
+ * This sets the text of the anchorblock to be the text given as @p text. This
+ * text is in markup format with \<a href=XXX\> beginning an achor with the
+ * string link of 'XXX', and \</\> or \</a\> ending the link. Other markup can
+ * be used dependign on the style support.
+ *
+ * @param obj The anchorblock object
+ * @param text The text to set, or NULL to clear
+ *
+ * @ingroup Anchorblock
+ */
+EAPI void
+elm_anchorblock_text_set(Evas_Object *obj, const char *text)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_entry_set(wd->entry, text);
+   if (wd->hover) evas_object_del(wd->hover);
+   if (wd->pop) evas_object_del(wd->pop);
+   wd->hover = NULL;
+   wd->pop = NULL;
+   _sizing_eval(obj);
+}
+
+/**
+  * Get the markup text set for the anchorblock
+  *
+  * This retrieves back the string set by @c elm_anchorblock_text_set().
+  *
+  * @param obj The anchorblock object
+  * @return text The markup text set or @c NULL, either if it was not set
+  * or an error occurred
+  *
+  * @ingroup Anchorblock
+  */
+EAPI const char*
+elm_anchorblock_text_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_entry_entry_get(wd->entry);
+}
+
+/**
+ * Set the parent of the hover popup
+ *
+ * This sets the parent of the hover that anchorblock will create. See hover
+ * objects for more information on this.
+ *
+ * @param obj The anchorblock object
+ * @param parent The parent the hover should use
+ *
+ * @ingroup Anchorblock
+ */
+EAPI void
+elm_anchorblock_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->hover_parent)
+     evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
+   wd->hover_parent = parent;
+   if (wd->hover_parent)
+     evas_object_event_callback_add(wd->hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
+}
+
+/**
+ * Get the parent of the hover popup
+ *
+ * This sgets the parent of the hover that anchorblock will create. See hover
+ * objects for more information on this.
+ *
+ * @param obj The anchorblock object
+ * @return The parent used by the hover
+ *
+ * @ingroup Anchorblock
+ */
+EAPI Evas_Object *
+elm_anchorblock_hover_parent_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->hover_parent;
+}
+
+/**
+ * Set the style that the hover should use
+ *
+ * This sets the style for the hover that anchorblock will create. See hover
+ * objects for more information
+ *
+ * @param obj The anchorblock object
+ * @param style The style to use
+ *
+ * @ingroup Anchorblock
+ */
+EAPI void
+elm_anchorblock_hover_style_set(Evas_Object *obj, const char *style)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->hover_style, style);
+}
+
+/**
+ * Get the style that the hover should use
+ *
+ * This gets the style for the hover that anchorblock will create. See hover
+ * objects for more information
+ *
+ * @param obj The anchorblock object
+ * @return The style defined
+ *
+ * @ingroup Anchorblock
+ */
+EAPI const char *
+elm_anchorblock_hover_style_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->hover_style;
+}
+
+/**
+ * Stop the hover popup in the anchorblock
+ *
+ * This will stop the hover popup in the anchorblock if it is currently active.
+ *
+ * @param obj The anchorblock object
+ *
+ * @ingroup Anchorblock
+ */
+EAPI void
+elm_anchorblock_hover_end(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->hover) evas_object_del(wd->hover);
+   if (wd->pop) evas_object_del(wd->pop);
+   wd->hover = NULL;
+   wd->pop = NULL;
+}
+
+/**
+ * This appends a custom item provider to the list for that anchorblock
+ *
+ * This appends the given callback. The list is walked from beginning to end
+ * with each function called given the item href string in the text. If the
+ * function returns an object handle other than NULL (it should create an
+ * and object to do this), then this object is used to replace that item. If
+ * not the next provider is called until one provides an item object, or the
+ * default provider in anchorblock does.
+ * 
+ * @param obj The anchorblock object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Anchorblock
+ */
+EAPI void
+elm_anchorblock_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorblock, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Anchorblock_Item_Provider *ip = calloc(1, sizeof(Elm_Anchorblock_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_append(wd->item_providers, ip);
+}
+
+/**
+ * This prepends a custom item provider to the list for that anchorblock
+ *
+ * This prepends the given callback. See elm_anchorblock_item_provider_append() for
+ * more information
+ * 
+ * @param obj The anchorblock object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Anchorblock
+ */
+EAPI void
+elm_anchorblock_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorblock, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Anchorblock_Item_Provider *ip = calloc(1, sizeof(Elm_Anchorblock_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_prepend(wd->item_providers, ip);
+}
+
+/**
+ * This removes a custom item provider to the list for that anchorblock
+ *
+ * This removes the given callback. See elm_anchorblock_item_provider_append() for
+ * more information
+ * 
+ * @param obj The anchorblock object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Anchorblock
+ */
+EAPI void
+elm_anchorblock_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorblock, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Anchorblock_Item_Provider *ip;
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        if ((ip->func == func) && (ip->data == data))
+          {
+             wd->item_providers = eina_list_remove_list(wd->item_providers, l);
+             free(ip);
+             return;
+          }
+     }
+}
diff --git a/src/lib/elc_anchorview.c b/src/lib/elc_anchorview.c
new file mode 100644 (file)
index 0000000..df61e53
--- /dev/null
@@ -0,0 +1,494 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Anchorview Anchorview
+ *
+ * This is just like the Anchorblock object, but provides a scroller to hold
+ * the text automatically.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * anchor,clicked - achor called was clicked. event_info is anchor info -
+ * Elm_Entry_Anchorview_Info
+ */
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Elm_Anchorview_Item_Provider Elm_Anchorview_Item_Provider;
+
+struct _Widget_Data
+{
+   Evas_Object *scroller, *entry;
+   Evas_Object *hover_parent;
+   Evas_Object *pop, *hover;
+   Eina_List *item_providers;
+   const char *hover_style;
+};
+
+struct _Elm_Anchorview_Item_Provider
+{
+   Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item);
+   void *data;
+};
+
+static const char *widtype = NULL;
+
+static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_ANCHOR_CLICKED, ""}, /* TODO: declare the type properly, as data is
+                            * being passed
+                            */
+  {NULL, NULL}
+};
+
+static void _del_pre_hook(Evas_Object *obj);
+static void _del_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 _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   elm_anchorview_hover_end(obj);
+   elm_anchorview_hover_parent_set(obj, NULL);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Anchorview_Item_Provider *ip;
+   if (!wd) return;
+   if (wd->hover_style) eina_stringshare_del(wd->hover_style);
+   EINA_LIST_FREE(wd->item_providers, ip)
+     {
+        free(ip);
+     }
+   free(wd);
+}
+
+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_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__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_hover_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_anchorview_hover_end(data);
+}
+
+static void
+_anchor_clicked(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Elm_Entry_Anchor_Info *info = event_info;
+   Evas_Object *hover_parent;
+   Elm_Entry_Anchorview_Info ei;
+   Evas_Coord x, w, y, h, px, py;
+   if (!wd) return;
+   wd->pop = elm_icon_add(obj);
+   evas_object_move(wd->pop, info->x, info->y);
+   evas_object_resize(wd->pop, info->w, info->h);
+   wd->hover = elm_hover_add(obj);
+   if (wd->hover_style) elm_object_style_set(wd->hover, wd->hover_style);
+   hover_parent = wd->hover_parent;
+   if (!hover_parent) hover_parent = obj;
+   elm_hover_parent_set(wd->hover, hover_parent);
+   elm_hover_target_set(wd->hover, wd->pop);
+   ei.name = info->name;
+   ei.button = info->button;
+   ei.hover = wd->hover;
+   ei.anchor.x = info->x;
+   ei.anchor.y = info->y;
+   ei.anchor.w = info->w;
+   ei.anchor.h = info->h;
+   evas_object_geometry_get(hover_parent, &x, &y, &w, &h);
+   ei.hover_parent.x = x;
+   ei.hover_parent.y = y;
+   ei.hover_parent.w = w;
+   ei.hover_parent.h = h;
+   px = info->x + (info->w / 2);
+   py = info->y + (info->h / 2);
+   ei.hover_left = 1;
+   if (px < (x + (w / 3))) ei.hover_left = 0;
+   ei.hover_right = 1;
+   if (px > (x + ((w * 2) / 3))) ei.hover_right = 0;
+   ei.hover_top = 1;
+   if (py < (y + (h / 3))) ei.hover_top = 0;
+   ei.hover_bottom = 1;
+   if (py > (y + ((h * 2) / 3))) ei.hover_bottom = 0;
+   evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, &ei);
+   evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked, data);
+   evas_object_show(wd->hover);
+}
+
+static void
+_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->hover_parent = NULL;
+}
+
+static Evas_Object *
+_item_provider(void *data, Evas_Object *entry __UNUSED__, const char *item)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Eina_List *l;
+   Elm_Anchorview_Item_Provider *ip;
+   
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        Evas_Object *o;
+
+        o = ip->func(ip->data, data, item);
+        if (o) return o;
+     }
+   return NULL;
+}
+
+/**
+ * Add a new Anchorview object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Anchorview
+ */
+EAPI Evas_Object *
+elm_anchorview_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "anchorview");
+   elm_widget_type_set(obj, "anchorview");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   elm_widget_del_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+
+   wd->scroller = elm_scroller_add(parent);
+   elm_widget_resize_object_set(obj, wd->scroller);
+   wd->entry = elm_entry_add(parent);
+   elm_entry_item_provider_prepend(wd->entry, _item_provider, obj);
+   elm_entry_editable_set(wd->entry, 0);
+   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->scroller, wd->entry);
+   evas_object_show(wd->entry);
+
+   evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                 _changed_size_hints, obj);
+
+   elm_entry_entry_set(wd->entry, "");
+
+   evas_object_smart_callback_add(wd->entry, "anchor,clicked",
+                                 _anchor_clicked, obj);
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+  * Set the text markup of the anchorview
+  *
+  * This sets the text of the anchorview to be the text given as @p text. This
+  * text is in markup format with \<a href=XXX\> beginning an achor with the
+  * string link of 'XXX', and \</\> or \</a\> ending the link. Other markup can
+  * be used dependign on the style support.
+  *
+  * @param obj The anchorview object
+  * @param text The text to set, or NULL to clear
+  *
+  * @ingroup Anchorview
+  */
+EAPI void
+elm_anchorview_text_set(Evas_Object *obj, const char *text)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_entry_set(wd->entry, text);
+   if (wd->hover) evas_object_del(wd->hover);
+   if (wd->pop) evas_object_del(wd->pop);
+   wd->hover = NULL;
+   wd->pop = NULL;
+   _sizing_eval(obj);
+}
+
+/**
+  * Get the markup text set for the anchorview
+  *
+  * This retrieves back the string set by @c elm_anchorview_text_set().
+  *
+  * @param obj The anchorview object
+  * @return text The markup text set or @c NULL, either if it was not set
+  * or an error occurred
+  *
+  * @ingroup Anchorview
+  */
+EAPI const char*
+elm_anchorview_text_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_entry_entry_get(wd->entry);
+}
+
+/**
+  * Set the parent of the hover popup
+  *
+  * This sets the parent of the hover that anchorview will create. See hover
+  * objects for more information on this.
+  *
+  * @param obj The anchorview object
+  * @param parent The parent the hover should use
+  *
+  * @ingroup Anchorview
+  */
+EAPI void
+elm_anchorview_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->hover_parent)
+     evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
+   wd->hover_parent = parent;
+   if (wd->hover_parent)
+     evas_object_event_callback_add(wd->hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
+}
+
+/**
+  * Get the parent of the hover popup
+  *
+  * This gets the parent of the hover that anchorview will created. See hover
+  * objects for more information on this.
+  *
+  * @param obj The anchorview object
+  * @return The parent used by hover
+  *
+  * @ingroup Anchorview
+  */
+EAPI Evas_Object *
+elm_anchorview_hover_parent_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->hover_parent;
+}
+
+/**
+  * Set the style that the hover should use
+  *
+  * This sets the style for the hover that anchorview will create. See hover
+  * objects for more information
+  *
+  * @param obj The anchorview object
+  * @param style The style to use
+  *
+  * @ingroup Anchorview
+  */
+EAPI void
+elm_anchorview_hover_style_set(Evas_Object *obj, const char *style)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->hover_style, style);
+}
+
+/**
+ * Get the style that the hover should use
+ *
+ * This gets the style for the hover that anchorview will create. See hover
+ * objects for more information
+ *
+ * @param obj The anchorview object
+ * @return The style defined
+ *
+ * @ingroup Anchorview
+ */
+EAPI const char *
+elm_anchorview_hover_style_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->hover_style;
+}
+
+/**
+  * Stop the hover popup in the anchorview
+  *
+  * This will stop the hover popup in the anchorview if it is currently active.
+  *
+  * @param obj The anchorview object
+  *
+  * @ingroup Anchorview
+  */
+EAPI void
+elm_anchorview_hover_end(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->hover) evas_object_del(wd->hover);
+   if (wd->pop) evas_object_del(wd->pop);
+   wd->hover = NULL;
+   wd->pop = NULL;
+}
+
+/**
+ * Set bounce mode
+ *
+ * This will enable or disable the scroller bounce mode for the anchorview. See
+ * elm_scroller_bounce_set() for details
+ *
+ * @param obj The anchorview anchorview
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Anchorview
+ */
+EAPI void
+elm_anchorview_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->scroller, h_bounce, v_bounce);
+}
+
+/**
+ * Get the bounce mode
+ *
+ * @param obj The Anchorview object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Anchorview
+ */
+EAPI void
+elm_anchorview_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_scroller_bounce_get(wd->scroller, h_bounce, v_bounce);
+}
+
+/**
+ * This appends a custom item provider to the list for that anchorview
+ *
+ * This appends the given callback. The list is walked from beginning to end
+ * with each function called given the item href string in the text. If the
+ * function returns an object handle other than NULL (it should create an
+ * and object to do this), then this object is used to replace that item. If
+ * not the next provider is called until one provides an item object, or the
+ * default provider in anchorview does.
+ * 
+ * @param obj The anchorview object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Anchorview
+ */
+EAPI void
+elm_anchorview_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Anchorview_Item_Provider *ip = calloc(1, sizeof(Elm_Anchorview_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_append(wd->item_providers, ip);
+}
+
+/**
+ * This prepends a custom item provider to the list for that anchorview
+ *
+ * This prepends the given callback. See elm_anchorview_item_provider_append() for
+ * more information
+ * 
+ * @param obj The anchorview object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Anchorview
+ */
+EAPI void
+elm_anchorview_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Anchorview_Item_Provider *ip = calloc(1, sizeof(Elm_Anchorview_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_prepend(wd->item_providers, ip);
+}
+
+/**
+ * This removes a custom item provider to the list for that anchorview
+ *
+ * This removes the given callback. See elm_anchorview_item_provider_append() for
+ * more information
+ * 
+ * @param obj The anchorview object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Anchorview
+ */
+EAPI void
+elm_anchorview_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Anchorview_Item_Provider *ip;
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        if ((ip->func == func) && (ip->data == data))
+          {
+             wd->item_providers = eina_list_remove_list(wd->item_providers, l);
+             free(ip);
+             return;
+          }
+     }
+}
diff --git a/src/lib/elc_ctxpopup.c b/src/lib/elc_ctxpopup.c
new file mode 100644 (file)
index 0000000..6454967
--- /dev/null
@@ -0,0 +1,1563 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Ctxpopup
+ *
+ * A ctxpopup is a widget that, when shown, pops up a list of items.
+ * It automatically chooses an area inside its parent object's view
+ * (set via elm_ctxpopup_add() and elm_ctxpopup_hover_parent_set()) to
+ * optimally fit into it. In the default theme, it will also point an
+ * arrow to the cursor position at the time one shows it. Ctxpopup
+ * items have a label and/or an icon. It is intended for a small
+ * number of items (hence the use of list, not genlist).
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * dismissed - the ctxpopup was dismissed
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Elm_Ctxpopup_Item
+{
+   Elm_Widget_Item base;
+   const char *label;
+   Evas_Object *icon;
+   Evas_Smart_Cb func;
+   Eina_Bool disabled:1;
+};
+
+struct _Widget_Data
+{
+   Evas_Object *parent;
+   Evas_Object *base;
+   Evas_Object *content;
+   Evas_Object *box;
+   Evas_Object *arrow;
+   Evas_Object *scr;
+   Evas_Object *bg;
+   Evas_Object *hover_parent;
+   Eina_List *items;
+   Elm_Ctxpopup_Direction dir;
+   Elm_Ctxpopup_Direction dir_priority[4];
+   Evas_Coord max_sc_w, max_sc_h;
+   Eina_Bool horizontal:1;
+   Eina_Bool visible:1;
+   Eina_Bool finished:1;
+};
+
+static const char *widtype = NULL;
+
+static void _del_hook(Evas_Object *obj);
+static void _del_pre_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _hover_parent_resize(void *data, Evas *e __UNUSED__,
+                                 Evas_Object *obj __UNUSED__,
+                                 void *event_info __UNUSED__);
+static void _hover_parent_move(void *data, Evas *e __UNUSED__,
+                               Evas_Object *obj __UNUSED__,
+                               void *event_info __UNUSED__);
+static void _hover_parent_del(void *data, Evas *e __UNUSED__,
+                              Evas_Object *obj __UNUSED__,
+                              void *event_info __UNUSED__);
+static void _hover_parent_callbacks_del(Evas_Object *obj);
+static void _bg_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
+                           const char *emission __UNUSED__,
+                           const char *source __UNUSED__);
+static void _parent_resize(void *data, Evas *e, Evas_Object *obj,
+                           void *event_info __UNUSED__);
+static void _ctxpopup_show(void *data __UNUSED__, Evas *e __UNUSED__,
+                           Evas_Object *obj, void *event_info __UNUSED__);
+static void _ctxpopup_hide(void *data __UNUSED__, Evas *e __UNUSED__,
+                           Evas_Object *obj, void *event_info __UNUSED__);
+static void _ctxpopup_move(void *data __UNUSED__, Evas *e __UNUSED__,
+                           Evas_Object *obj, void *event_info __UNUSED__);
+static void _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
+                             void *event_info __UNUSED__);
+static void _ctxpopup_changed_size_hints(void *data __UNUSED__,
+                                         Evas *e __UNUSED__, Evas_Object *obj,
+                                         void *event_info __UNUSED__);
+static void _item_new(Elm_Ctxpopup_Item *item, char *group_name);
+static void _list_new(Evas_Object *obj);
+static void _item_sizing_eval(Elm_Ctxpopup_Item *item);
+static void _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
+                            const char *emission __UNUSED__,
+                            const char *source __UNUSED__);
+static Elm_Ctxpopup_Direction _calc_base_geometry(Evas_Object *obj,
+                                                  Evas_Coord_Rectangle *rect);
+static void _update_arrow(Evas_Object *obj, Elm_Ctxpopup_Direction dir);
+static void _shift_base_by_arrow(Evas_Object *arrow,
+                                 Elm_Ctxpopup_Direction dir,
+                                 Evas_Coord_Rectangle *rect);
+static void _adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size,
+                          Evas_Coord_Rectangle *hover_area);
+static void _adjust_pos_y(Evas_Coord_Point *pos, Evas_Coord_Point *base_size,
+                          Evas_Coord_Rectangle *hover_area);
+static void _scroller_size_reset(Widget_Data *wd);
+static void _hide(Evas_Object *obj);
+static void _content_del(void *data, Evas *e, Evas_Object *obj __UNUSED__,
+                         void *event_info __UNUSED__);
+static void _freeze_on(void *data __UNUSED__, Evas_Object *obj,
+                       void *event_info __UNUSED__);
+static void _freeze_off(void *data __UNUSED__, Evas_Object *obj,
+                        void *event_info __UNUSED__);
+static void _hold_on(void *data __UNUSED__, Evas_Object *obj,
+                     void *event_info __UNUSED__);
+static void _hold_off(void *data __UNUSED__, Evas_Object *obj,
+                      void *event_info __UNUSED__);
+static void _item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon);
+static void _item_label_set(Elm_Ctxpopup_Item *item, const char *label);
+static void _remove_items(Widget_Data * wd);
+
+static const char SIG_DISMISSED[] = "dismissed";
+
+static const Evas_Smart_Cb_Description _signals[] = {
+   {SIG_DISMISSED, ""},
+   {NULL, NULL}
+};
+
+#define ELM_CTXPOPUP_ITEM_CHECK_RETURN(it, ...)                        \
+  ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
+  ELM_CHECK_WIDTYPE(item->base.widget, widtype) __VA_ARGS__;
+
+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_object_scroll_freeze_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_object_scroll_freeze_pop(wd->scr);
+}
+
+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_object_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_object_scroll_hold_pop(wd->scr);
+}
+
+static void
+_scroller_size_reset(Widget_Data *wd)
+{
+   wd->finished = EINA_FALSE;
+   wd->max_sc_h = -1;
+   wd->max_sc_w = -1;
+}
+
+static void
+_hover_parent_callbacks_del(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if ((!wd) || (!wd->hover_parent))
+      return;
+
+   evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL,
+                                       _hover_parent_del, obj);
+   evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_MOVE,
+                                       _hover_parent_move, obj);
+   evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_RESIZE,
+                                       _hover_parent_resize, obj);
+}
+
+static void
+_hover_parent_resize(void *data, Evas *e __UNUSED__,
+                     Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd)
+      return;
+
+   if (wd->visible)
+     {
+        _scroller_size_reset(wd);
+        _sizing_eval(data);
+     }
+}
+
+static void
+_hover_parent_move(void *data, Evas *e __UNUSED__,
+                   Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd)
+      return;
+
+   if (wd->visible)
+     {
+        _scroller_size_reset(wd);
+        _sizing_eval(obj);
+     }
+}
+
+static void
+_hover_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
+                  void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd)
+      return;
+
+   wd->hover_parent = NULL;
+}
+
+static void
+_item_sizing_eval(Elm_Ctxpopup_Item *item)
+{
+   Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
+
+   Evas_Coord x, y, w, h;
+
+   if (!item)
+      return;
+
+   evas_object_geometry_get(item->base.view, &x, &y, &w, &h);
+   edje_object_size_min_restricted_calc(item->base.view, &min_w, &min_h, min_w,
+                                        min_h);
+   evas_object_size_hint_min_set(item->base.view, min_w, min_h);
+   evas_object_size_hint_max_set(item->base.view, max_w, max_h);
+}
+
+static void
+_adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size,
+              Evas_Coord_Rectangle *hover_area)
+{
+   pos->x -= (base_size->x / 2);
+
+   if (pos->x < hover_area->x)
+      pos->x = hover_area->x;
+   else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
+      pos->x = (hover_area->x + hover_area->w) - base_size->x;
+
+   if (base_size->x > hover_area->w)
+      base_size->x -= (base_size->x - hover_area->w);
+
+   if (pos->x < hover_area->x)
+      pos->x = hover_area->x;
+}
+
+static void
+_adjust_pos_y(Evas_Coord_Point *pos, Evas_Coord_Point *base_size,
+              Evas_Coord_Rectangle *hover_area)
+{
+   pos->y -= (base_size->y / 2);
+
+   if (pos->y < hover_area->y)
+      pos->y = hover_area->y;
+   else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
+      pos->y = hover_area->y + hover_area->h - base_size->y;
+
+   if (base_size->y > hover_area->h)
+      base_size->y -= (base_size->y - hover_area->h);
+
+   if (pos->y < hover_area->y)
+      pos->y = hover_area->y;
+}
+
+static void
+_ctxpopup_changed_size_hints(void *data __UNUSED__, Evas *e __UNUSED__,
+                             Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   if (wd->visible)
+      _sizing_eval(obj);
+}
+
+static Elm_Ctxpopup_Direction
+_calc_base_geometry(Evas_Object *obj, Evas_Coord_Rectangle *rect)
+{
+   Widget_Data *wd;
+   Evas_Coord_Point pos = {0, 0};
+   Evas_Coord_Point base_size;
+   Evas_Coord_Point max_size;
+   Evas_Coord_Point min_size;
+   Evas_Coord_Rectangle hover_area;
+   Evas_Coord_Rectangle parent_size;
+   Evas_Coord_Point arrow_size;
+   Elm_Ctxpopup_Direction arrow = ELM_CTXPOPUP_DIRECTION_DOWN;
+   Evas_Coord finger_size;
+   Evas_Coord_Point temp;
+   int idx;
+
+   wd = elm_widget_data_get(obj);
+
+   if ((!wd) || (!rect))
+      return ELM_CTXPOPUP_DIRECTION_DOWN;
+
+   finger_size = elm_finger_size_get();
+
+   edje_object_part_geometry_get(wd->arrow, "ctxpopup_arrow", NULL, NULL,
+                                 &arrow_size.x, &arrow_size.y);
+   evas_object_resize(wd->arrow, arrow_size.x, arrow_size.y);
+
+   //Initialize Area Rectangle. 
+   if (wd->hover_parent)
+      evas_object_geometry_get(wd->hover_parent, &hover_area.x, &hover_area.y,
+                               &hover_area.w, &hover_area.h);
+   else
+     {
+        evas_object_geometry_get(wd->parent, &parent_size.x, &parent_size.y,
+                                 &parent_size.w, &parent_size.h);
+        hover_area.x = parent_size.x;
+        hover_area.y = parent_size.y;
+        hover_area.w = parent_size.w;
+        hover_area.h = parent_size.h;
+     }
+
+   evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
+
+   //recalc the edje 
+   edje_object_size_min_calc(wd->base, &base_size.x, &base_size.y);
+   evas_object_smart_calculate(wd->base);
+
+   //Limit to Max Size
+   evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
+
+   if ((max_size.y > 0) && (base_size.y > max_size.y))
+      base_size.y = max_size.y;
+
+   if ((max_size.x > 0) && (base_size.x > max_size.x))
+      base_size.x = max_size.x;
+
+   //Limit to Min Size 
+   evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
+
+   if ((min_size.y > 0) && (base_size.y < min_size.y))
+      base_size.y = min_size.y;
+
+   if ((min_size.x > 0) && (base_size.x < min_size.x))
+      base_size.x = min_size.x;
+
+   //Check the Which direction is available.
+   //If find a avaialble direction, it adjusts position and size. 
+   for (idx = 0; idx < 4; idx++)
+     {
+        switch (wd->dir_priority[idx])
+          {
+           case ELM_CTXPOPUP_DIRECTION_UP:
+              temp.y = pos.y - base_size.y;
+              if ((temp.y - arrow_size.y - finger_size) < hover_area.y)
+                 continue;
+              _adjust_pos_x(&pos, &base_size, &hover_area);
+              pos.y -= (base_size.y + finger_size);
+              arrow = ELM_CTXPOPUP_DIRECTION_DOWN;
+              break;
+           case ELM_CTXPOPUP_DIRECTION_LEFT:
+              temp.x = (pos.x - base_size.x);
+              if ((temp.x - arrow_size.x - finger_size) < hover_area.x)
+                 continue;
+              _adjust_pos_y(&pos, &base_size, &hover_area);
+              pos.x -= (base_size.x + finger_size);
+              arrow = ELM_CTXPOPUP_DIRECTION_RIGHT;
+              break;
+           case ELM_CTXPOPUP_DIRECTION_RIGHT:
+              temp.x = (pos.x + base_size.x);
+              if ((temp.x + arrow_size.x + finger_size) >
+                  (hover_area.x + hover_area.w))
+                 continue;
+              _adjust_pos_y(&pos, &base_size, &hover_area);
+              pos.x += finger_size;
+              arrow = ELM_CTXPOPUP_DIRECTION_LEFT;
+              break;
+           case ELM_CTXPOPUP_DIRECTION_DOWN:
+              temp.y = (pos.y + base_size.y);
+              if ((temp.y + arrow_size.y + finger_size) >
+                  (hover_area.y + hover_area.h))
+                 continue;
+              _adjust_pos_x(&pos, &base_size, &hover_area);
+              pos.y += finger_size;
+              arrow = ELM_CTXPOPUP_DIRECTION_UP;
+              break;
+           default:
+              break;
+          }
+        break;
+     }
+
+   //In this case, all directions are invalid because of lack of space.
+   if (idx == 4)
+     {
+        //TODO 1: Find the largest space direction.
+        Evas_Coord length[2];
+
+        length[0] = pos.y - hover_area.y;
+        length[1] = (hover_area.y + hover_area.h) - pos.y;
+
+        if (length[0] > length[1])
+           idx = ELM_CTXPOPUP_DIRECTION_DOWN;
+        else
+           idx = ELM_CTXPOPUP_DIRECTION_UP;
+
+        //TODO 2: determine x , y
+        switch (idx)
+          {
+           case ELM_CTXPOPUP_DIRECTION_UP:
+              _adjust_pos_x(&pos, &base_size, &hover_area);
+              pos.y -= (base_size.y + finger_size);
+              arrow = ELM_CTXPOPUP_DIRECTION_DOWN;
+              if (pos.y < hover_area.y + arrow_size.y)
+                {
+                   base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
+                   pos.y = hover_area.y + arrow_size.y;
+                }
+              break;
+           case ELM_CTXPOPUP_DIRECTION_LEFT:
+              _adjust_pos_y(&pos, &base_size, &hover_area);
+              pos.x -= (base_size.x + finger_size);
+              arrow = ELM_CTXPOPUP_DIRECTION_RIGHT;
+              if (pos.x < hover_area.x + arrow_size.x)
+                {
+                   base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
+                   pos.x = hover_area.x + arrow_size.x;
+                }
+              break;
+           case ELM_CTXPOPUP_DIRECTION_RIGHT:
+              _adjust_pos_y(&pos, &base_size, &hover_area);
+              pos.x += finger_size;
+              arrow = ELM_CTXPOPUP_DIRECTION_LEFT;
+              if (pos.x + arrow_size.x + base_size.x >
+                  hover_area.x + hover_area.w)
+                 base_size.x -=
+                    ((pos.x + arrow_size.x + base_size.x) -
+                     (hover_area.x + hover_area.w));
+              break;
+           case ELM_CTXPOPUP_DIRECTION_DOWN:
+              _adjust_pos_x(&pos, &base_size, &hover_area);
+              pos.y += finger_size;
+              arrow = ELM_CTXPOPUP_DIRECTION_UP;
+              if (pos.y + arrow_size.y + base_size.y >
+                  hover_area.y + hover_area.h)
+                 base_size.y -=
+                    ((pos.y + arrow_size.y + base_size.y) -
+                     (hover_area.y + hover_area.h));
+              break;
+           default:
+              break;
+          }
+     }
+
+   //Final position and size. 
+   rect->x = pos.x;
+   rect->y = pos.y;
+   rect->w = base_size.x;
+   rect->h = base_size.y;
+
+   return arrow;
+}
+
+static void
+_update_arrow(Evas_Object *obj, Elm_Ctxpopup_Direction dir)
+{
+   Evas_Coord x, y;
+   Evas_Coord_Rectangle arrow_size;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   evas_object_geometry_get(wd->arrow, NULL, NULL, &arrow_size.w,
+                            &arrow_size.h);
+
+   switch (dir)
+     {
+      case ELM_CTXPOPUP_DIRECTION_LEFT:
+         edje_object_signal_emit(wd->arrow, "elm,state,left", "elm");
+         arrow_size.y = (y - (arrow_size.h * 0.5));
+         arrow_size.x = (x + elm_finger_size_get());
+         break;
+      case ELM_CTXPOPUP_DIRECTION_RIGHT:
+         edje_object_signal_emit(wd->arrow, "elm,state,right", "elm");
+         arrow_size.y = (y - (arrow_size.h * 0.5));
+         arrow_size.x = (x - elm_finger_size_get() - arrow_size.w);
+         break;
+      case ELM_CTXPOPUP_DIRECTION_UP:
+         edje_object_signal_emit(wd->arrow, "elm,state,top", "elm");
+         arrow_size.x = (x - (arrow_size.w * 0.5));
+         arrow_size.y = (y + elm_finger_size_get());
+         break;
+      case ELM_CTXPOPUP_DIRECTION_DOWN:
+         edje_object_signal_emit(wd->arrow, "elm,state,bottom", "elm");
+         arrow_size.x = (x - (arrow_size.w * 0.5));
+         arrow_size.y = (y - elm_finger_size_get() - arrow_size.h);
+         break;
+      default:
+         break;
+     }
+
+   evas_object_move(wd->arrow, arrow_size.x, arrow_size.y);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   Eina_List *elist;
+   Elm_Ctxpopup_Item *item;
+   Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
+   Evas_Coord_Point box_size = { 0, 0 };
+   Evas_Coord_Point _box_size = { 0, 0 };
+
+   wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->parent))
+      return;
+
+   //Box, Scroller 
+   EINA_LIST_FOREACH(wd->items, elist, item)
+     {
+        _item_sizing_eval(item);
+        evas_object_size_hint_min_get(item->base.view, &_box_size.x, &_box_size.y);
+        if (!wd->horizontal)
+          {
+             if (_box_size.x > box_size.x)
+                box_size.x = _box_size.x;
+             if (_box_size.y != -1)
+                box_size.y += _box_size.y;
+          }
+        else
+          {
+             if (_box_size.x != -1)
+                box_size.x += _box_size.x;
+             if (_box_size.y > box_size.y)
+                box_size.y = _box_size.y;
+          }
+     }
+
+   if (!wd->content)
+     {
+        evas_object_size_hint_min_set(wd->box, box_size.x, box_size.y);
+        evas_object_size_hint_min_set(wd->scr, box_size.x, box_size.y);
+     }
+
+   //Base
+   wd->dir = _calc_base_geometry(obj, &rect);
+   _update_arrow(obj, wd->dir);
+   _shift_base_by_arrow(wd->arrow, wd->dir, &rect);
+
+   //resize scroller according to final size. 
+   if (!wd->content)
+      evas_object_smart_calculate(wd->scr); 
+
+   evas_object_move(wd->base, rect.x, rect.y);
+   evas_object_resize(wd->base, rect.w, rect.h);
+}
+
+static void
+_shift_base_by_arrow(Evas_Object *arrow, Elm_Ctxpopup_Direction dir,
+                     Evas_Coord_Rectangle *rect)
+{
+   Evas_Coord arrow_w, arrow_h;
+
+   evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
+
+   switch (dir)
+     {
+      case ELM_CTXPOPUP_DIRECTION_LEFT:
+         rect->x += arrow_w;
+         break;
+      case ELM_CTXPOPUP_DIRECTION_RIGHT:
+         rect->x -= arrow_w;
+         break;
+      case ELM_CTXPOPUP_DIRECTION_UP:
+         rect->y += arrow_h;
+         break;
+      case ELM_CTXPOPUP_DIRECTION_DOWN:
+         rect->y -= arrow_h;
+         break;
+      default:
+         break;
+     }
+}
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
+                                       _parent_resize, obj);
+
+   _hover_parent_callbacks_del(obj);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   elm_ctxpopup_clear(obj);
+   evas_object_del(wd->arrow);
+   evas_object_del(wd->base);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   Eina_List *elist;
+   Elm_Ctxpopup_Item *item;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   //Items
+   EINA_LIST_FOREACH(wd->items, elist, item)
+     {
+        if (item->label && item->icon)
+           _elm_theme_object_set(obj, item->base.view, "ctxpopup",
+                                 "icon_text_style_item",
+                                 elm_widget_style_get(obj));
+        else if (item->label)
+           _elm_theme_object_set(obj, item->base.view, "ctxpopup", "text_style_item",
+                                 elm_widget_style_get(obj));
+        else if (item->icon)
+           _elm_theme_object_set(obj, item->base.view, "ctxpopup", "icon_style_item",
+                                 elm_widget_style_get(obj));
+        if (item->label)
+           edje_object_part_text_set(item->base.view, "elm.text", item->label);
+
+        if (item->disabled)
+           edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
+
+        edje_object_message_signal_process(item->base.view);
+     }
+
+   _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg",
+                         elm_widget_style_get(obj));
+   _elm_theme_object_set(obj, wd->base, "ctxpopup", "base",
+                         elm_widget_style_get(obj));
+   _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow",
+                         elm_widget_style_get(obj));
+
+   if (!strncmp(elm_object_style_get(obj), "default", 
+                strlen("default")))
+      elm_object_style_set(wd->scr, "ctxpopup");
+   else 
+      elm_object_style_set(wd->scr, elm_object_style_get(obj));
+
+   if (wd->visible)
+     {
+        _scroller_size_reset(wd);
+        _sizing_eval(obj);
+     }
+}
+
+static void
+_bg_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
+               const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   evas_object_hide(data);
+}
+
+static void
+_parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
+               void *event_info __UNUSED__)
+{
+   Evas_Coord w, h;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(data);
+   if (!wd)
+      return;
+
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   evas_object_resize(wd->bg, w, h);
+
+   if (!wd->visible)
+      return;
+
+   _hide(data);
+}
+
+static void
+_ctxpopup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+               void *event_info __UNUSED__)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   if ((!wd->items) && (!wd->content))
+      return;
+
+   wd->visible = EINA_TRUE;
+
+   evas_object_show(wd->bg);
+   evas_object_show(wd->base);
+   evas_object_show(wd->arrow);
+
+   edje_object_signal_emit(wd->bg, "elm,state,show", "elm");
+
+   _sizing_eval(obj);
+}
+
+static void
+_hide(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd)
+      return;
+
+   evas_object_hide(wd->bg);
+   evas_object_hide(wd->arrow);
+   evas_object_hide(wd->base);
+
+   _scroller_size_reset(wd);
+
+   evas_object_smart_callback_call(obj, SIG_DISMISSED, NULL);
+   wd->visible = EINA_FALSE;
+}
+
+static void
+_ctxpopup_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+               void *event_info __UNUSED__)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   if (!wd->visible)
+      return;
+
+   _hide(obj);
+}
+
+static void
+_scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
+                 void *event_info __UNUSED__)
+{
+   Widget_Data *wd;
+   Evas_Coord w, h;
+
+   wd = elm_widget_data_get(data);
+   if (!wd)
+      return;
+
+   if (!wd->visible)
+      return;
+   if (wd->finished)
+      return;
+
+   evas_object_geometry_get(obj, 0, 0, &w, &h);
+
+   if (w != 0 && h != 0)
+     {
+        if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
+          {
+             _sizing_eval(data);
+             wd->finished = EINA_TRUE;
+             return;
+          }
+     }
+
+   if (wd->max_sc_w < w)
+      wd->max_sc_w = w;
+   if (wd->max_sc_h < h)
+      wd->max_sc_h = h;
+
+   _sizing_eval(data);
+}
+
+static void
+_ctxpopup_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+               void *event_info __UNUSED__)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+
+   if (!wd)
+      return;
+
+   if (wd->visible)
+      evas_object_show(wd->arrow);
+
+   _scroller_size_reset(wd);
+   _sizing_eval(obj);
+}
+
+static void
+_item_select_cb(void *data, Evas_Object *obj __UNUSED__,
+                const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Elm_Ctxpopup_Item *item = data;
+
+   if (!item)
+      return;
+   if (item->disabled)
+      return;
+
+   if (item->func)
+      item->func((void*) item->base.data, item->base.widget, data);
+}
+
+static void
+_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon)
+{
+   if (item->icon)
+     {
+        elm_widget_sub_object_del(item->base.view, item->icon);
+        evas_object_del(item->icon);
+     }
+
+   item->icon = icon;
+   edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon);
+   edje_object_message_signal_process(item->base.view);
+}
+
+static void
+_item_label_set(Elm_Ctxpopup_Item *item, const char *label)
+{
+   if (!eina_stringshare_replace(&item->label, label))
+      return;
+
+   edje_object_part_text_set(item->base.view, "elm.text", label);
+   edje_object_message_signal_process(item->base.view);
+}
+
+static void
+_item_new(Elm_Ctxpopup_Item *item, char *group_name)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+      return;
+
+   item->base.view = edje_object_add(evas_object_evas_get(wd->base));
+   _elm_theme_object_set(item->base.widget, item->base.view, "ctxpopup", group_name,
+                         elm_widget_style_get(item->base.widget));
+   edje_object_signal_callback_add(item->base.view, "elm,action,click", "",
+                                   _item_select_cb, item);
+   evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(item->base.view);
+}
+
+static void
+_content_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
+             void *event_info __UNUSED__)
+{
+   elm_ctxpopup_content_unset(data);
+}
+
+static void
+_list_del(Widget_Data *wd)
+{
+   if (!wd->scr)
+      return;
+
+   edje_object_part_unswallow(wd->base, wd->scr);
+   evas_object_del(wd->scr);
+   wd->scr = NULL;
+   wd->box = NULL;
+}
+
+static void
+_list_new(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   //scroller
+   wd->scr = elm_scroller_add(obj);
+   elm_object_style_set(wd->scr, "ctxpopup");
+   evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
+                                  _scroller_resize, obj);  
+   edje_object_part_swallow(wd->base, "elm.swallow.content", wd->scr); 
+
+   //box
+   wd->box = elm_box_add(obj);
+   evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+
+   elm_scroller_content_set(wd->scr, wd->box);
+   elm_ctxpopup_horizontal_set(obj, wd->horizontal); 
+}
+
+/**
+ * Add a new Ctxpopup object to the parent.
+ *
+ * @param parent Parent object
+ * @return New object or @c NULL, if it cannot be created
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI Evas_Object *
+elm_ctxpopup_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord x, y, w, h;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e)
+      return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "ctxpopup");
+   elm_widget_type_set(obj, "ctxpopup");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   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);
+
+   wd->parent = parent;
+
+   //Background
+   wd->bg = edje_object_add(e);
+   elm_widget_sub_object_add(obj, wd->bg);
+   _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", "default");
+   evas_object_geometry_get(parent, &x, &y, &w, &h);
+   evas_object_move(wd->bg, x, y);
+   evas_object_resize(wd->bg, w, h);
+   edje_object_signal_callback_add(wd->bg, "elm,action,click", "",
+                                   _bg_clicked_cb, obj);
+
+   //Base
+   wd->base = edje_object_add(e);
+   elm_widget_sub_object_add(obj, wd->base);
+   _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", "default");
+
+   //Arrow
+   wd->arrow = edje_object_add(e);
+   elm_widget_sub_object_add(obj, wd->arrow);
+   _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", "default");
+
+   wd->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
+   wd->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
+   wd->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
+   wd->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
+
+   evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE, _parent_resize,
+                                  obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _ctxpopup_show,
+                                  NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _ctxpopup_hide,
+                                  NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _ctxpopup_move,
+                                  NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                  _ctxpopup_changed_size_hints, NULL);
+   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(obj, "scroll-hold-on", _hold_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
+
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+
+   return obj;
+}
+
+/**
+ * Get the icon object for the given ctxpopup item.
+ *
+ * @param item Ctxpopup item
+ * @return icon object or @c NULL, if the item does not have icon or an error occurred
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI Evas_Object *
+elm_ctxpopup_item_icon_get(const Elm_Ctxpopup_Item *item)
+{
+   ELM_CTXPOPUP_ITEM_CHECK_RETURN(item, NULL);
+   return item->icon;
+}
+
+/**
+ * Sets the side icon associated with the ctxpopup item  
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * You probably don't want, then, to have the <b>same</b> icon object
+ * set for more than one item of the list (when replacing one of its
+ * instances).
+ * 
+ * @param item Ctxpopup item
+ * @param icon Icon object to be set
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon)
+{
+   ELM_CTXPOPUP_ITEM_CHECK_RETURN(item);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+      return;
+
+   _item_icon_set(item, icon);
+
+   if (wd->visible)
+     {
+        _scroller_size_reset(wd);
+        _sizing_eval(item->base.widget);
+     }
+}
+
+/**
+ * Get the label object for the given ctxpopup item.
+ *
+ * @param item Ctxpopup item
+ * @return label object or @c NULL, if the item does not have label or an error occured
+ *
+ * @ingroup Ctxpopup
+ *
+ */
+EAPI const char *
+elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item)
+{
+   ELM_CTXPOPUP_ITEM_CHECK_RETURN(item, NULL);
+   return item->label;
+}
+
+/**
+ * (Re)set the label on the given ctxpopup item.
+ *
+ * @param item Ctxpopup item
+ * @param label String to set as label
+ * 
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label)
+{
+   ELM_CTXPOPUP_ITEM_CHECK_RETURN(item);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+      return;
+
+   _item_label_set(item, label);
+
+   if (wd->visible)
+     {
+        _scroller_size_reset(wd);
+        _sizing_eval(item->base.widget);
+     }
+}
+
+/**
+ * Set the Ctxpopup's parent 
+ * Set the parent object (it would much probably be the 
+ * window that the ctxpopup is in).
+ *
+ * @param obj The ctxpopup object
+ * @param area The parent to use
+ *
+ * @note elm_ctxpopup_add() will automatically call this function
+ * with its @c parent argument.
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *hover_parent)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   _hover_parent_callbacks_del(obj);
+
+   if (hover_parent)
+     {
+        evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_DEL,
+                                       _hover_parent_del, obj);
+        evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_MOVE,
+                                       _hover_parent_move, obj);
+        evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_RESIZE,
+                                       _hover_parent_resize, obj);
+     }
+
+   wd->hover_parent = hover_parent;
+}
+
+/**
+ * Get the Ctxpopup's parent 
+ *
+ * @param obj The ctxpopup object
+ *
+ * @see elm_ctxpopup_hover_parent_set() for more information
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI Evas_Object *
+elm_ctxpopup_hover_parent_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return NULL;
+
+   return wd->hover_parent;
+}
+
+static void
+_remove_items(Widget_Data *wd)
+{
+   Eina_List *elist;
+   Elm_Ctxpopup_Item *item;
+
+   if (!wd->items)
+      return;
+
+   EINA_LIST_FOREACH(wd->items, elist, item)
+     {
+        if (item->label)
+           eina_stringshare_del(item->label);
+        if (item->icon)
+           evas_object_del(item->icon);
+        wd->items = eina_list_remove(wd->items, item);
+        free(item);
+     }
+
+   wd->items = NULL;
+}
+
+/**
+ * Clear all items in the given ctxpopup object.
+ *
+ * @param obj Ctxpopup object
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_clear(Evas_Object * obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd)
+      return;
+
+   _remove_items(wd);
+   _list_del(wd);
+}
+
+/**
+ * Change the ctxpopup's orientation to horizontal or vertical.
+ *
+ * @param obj Ctxpopup object
+ * @param horizontal @c        EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   wd->horizontal = !!horizontal;
+
+   if ((!wd->scr) && (!wd->box))
+      return;
+
+   if (!horizontal)
+     {
+        elm_box_horizontal_set(wd->box, EINA_FALSE);
+        elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
+     }
+   else
+     {
+        elm_box_horizontal_set(wd->box, EINA_TRUE);
+        elm_scroller_bounce_set(wd->scr, EINA_TRUE, EINA_FALSE);
+     }
+
+   if (wd->visible)
+      _sizing_eval(obj);
+}
+
+/**
+ * Get the value of current ctxpopup object's orientation.
+ *
+ * @param obj Ctxpopup object
+ * @return @c EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical mode (or errors)
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI Eina_Bool
+elm_ctxpopup_horizontal_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return EINA_FALSE;
+
+   return wd->horizontal;
+}
+
+/**
+ * Add a new item to a ctxpopup object.
+ *
+ * Both a item list and a content could not be set at the same time!
+ * once you set add a item, the previous content will be removed. 
+ *
+ * @param obj Ctxpopup object
+ * @param icon Icon to be set on new item 
+ * @param label The Label of the new item 
+ * @param func Convenience function called when item selected
+ * @param data Data passed to @p func above
+ * @return A handle to the item added or @c NULL, on errors
+ * 
+ * @ingroup Ctxpopup
+ */
+EAPI Elm_Ctxpopup_Item *
+elm_ctxpopup_item_append(Evas_Object *obj, const char *label,
+                         Evas_Object *icon, Evas_Smart_Cb func,
+                         const void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Widget_Data *wd;
+   Elm_Ctxpopup_Item *item;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return NULL;
+
+   item = elm_widget_item_new(obj, Elm_Ctxpopup_Item);
+   if (!item)
+      return NULL;
+
+   //The first item is appended.
+   if (wd->content)
+      evas_object_del(elm_ctxpopup_content_unset(obj));
+
+   if (!wd->items)
+      _list_new(obj);
+
+   item->func = func;
+   item->base.data = data;
+
+   if (icon && label)
+      _item_new(item, "icon_text_style_item");
+   else if (label)
+      _item_new(item, "text_style_item");
+   else 
+      _item_new(item, "icon_style_item");
+
+   _item_icon_set(item, icon);
+   _item_label_set(item, label);
+   elm_box_pack_end(wd->box, item->base.view);
+   wd->items = eina_list_append(wd->items, item);
+
+   if (wd->visible)
+     {
+        _scroller_size_reset(wd);
+        _sizing_eval(obj);
+     }
+
+   return item;
+}
+
+/**
+ * Delete the given item in a ctxpopup object.
+ *
+ * @param item Ctxpopup item to be deleted
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item)
+{
+   ELM_CTXPOPUP_ITEM_CHECK_RETURN(item);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+      return;
+
+   if (item->icon)
+      evas_object_del(item->icon);
+   if (item->base.view)
+      evas_object_del(item->base.view);
+
+   eina_stringshare_del(item->label);
+
+   wd->items = eina_list_remove(wd->items, item);
+
+   if (eina_list_count(wd->items) < 1)
+      wd->items = NULL;
+
+   if (wd->visible)
+      _sizing_eval(item->base.widget);
+
+   free(item);
+}
+
+/**
+ * Set the ctxpopup item's state as disabled or enabled.
+ *
+ * @param item Ctxpopup item to be enabled/disabled
+ * @param disabled @c EINA_TRUE to disable it, @c EINA_FALSE to enable it
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled)
+{
+   ELM_CTXPOPUP_ITEM_CHECK_RETURN(item);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+      return;
+
+   if (disabled == item->disabled)
+      return;
+
+   if (disabled)
+      edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
+   else
+      edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm");
+
+   item->disabled = !!disabled;
+}
+
+/**
+ * Get the ctxpopup item's disabled/enabled state.
+ *
+ * @param item Ctxpopup item to be enabled/disabled
+ * @return disabled @c EINA_TRUE, if disabled, @c EINA_FALSE otherwise
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI Eina_Bool
+elm_ctxpopup_item_disabled_get(const Elm_Ctxpopup_Item *item)
+{
+   ELM_CTXPOPUP_ITEM_CHECK_RETURN(item, EINA_FALSE);
+
+   return item->disabled;
+}
+
+/**
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the 
+ * elm_ctxpopup_content_unset() function
+ * 
+ * Both a item list and a content could not be set at the same time!
+ * once you set a content, the previous list items will be removed. 
+ *
+ * @param obj Ctxpopup object
+ * @param content      Content to be swallowed
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if ((!wd) || (!content))
+      return;
+
+   if (wd->items)
+      elm_ctxpopup_clear(obj);
+
+   if (wd->content)
+      evas_object_del(wd->content);
+
+   evas_object_event_callback_add(content, EVAS_CALLBACK_DEL, _content_del,
+                                  obj);
+
+   elm_widget_sub_object_add(obj, content);
+   edje_object_part_swallow(wd->base, "elm.swallow.content", content);
+   edje_object_message_signal_process(wd->base);
+
+   wd->content = content;
+
+   if (wd->visible)
+      _sizing_eval(obj);
+}
+
+/**
+ * Unset the ctxpopup content
+ *
+ * Unparent and return the content object which was set for this widget
+ * 
+ * @param obj Ctxpopup object
+ * @return The content that was being used
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI Evas_Object *
+elm_ctxpopup_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Widget_Data *wd;
+   Evas_Object *content;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return NULL;
+
+   content = wd->content;
+   if (!content)
+      return NULL;
+
+   edje_object_part_unswallow(wd->base, content);
+   elm_widget_sub_object_del(obj, content);
+   evas_object_event_callback_del(content, EVAS_CALLBACK_DEL, _content_del);
+   edje_object_signal_emit(wd->base, "elm,state,content,disable", "elm");
+
+   wd->content = NULL;
+
+   return content;
+}
+
+/**
+ * Set the direction priority of a ctxpopup.
+ * This functions gives a chance to user to set the priority of ctxpopup showing direction.
+ *
+ * @param obj Ctxpopup object
+ * @param first 1st priority of direction
+ * @param second 2nd priority of direction
+ * @param third 3th priority of direction
+ * @param fourth 4th priority of direction
+ *
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_direction_priority_set(Evas_Object *obj,
+                                    Elm_Ctxpopup_Direction first,
+                                    Elm_Ctxpopup_Direction second,
+                                    Elm_Ctxpopup_Direction third,
+                                    Elm_Ctxpopup_Direction fourth)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   wd->dir_priority[0] = first;
+   wd->dir_priority[1] = second;
+   wd->dir_priority[2] = third;
+   wd->dir_priority[3] = fourth;
+
+   if (wd->visible)
+      _sizing_eval(obj);
+}
+
+/**
+ * Get the direction priority of a ctxpopup.
+ *
+ * @param obj Ctxpopup object
+ * @param first 1st priority of direction to be returned
+ * @param second 2nd priority of direction to be returned 
+ * @param third 3th priority of direction to be returned 
+ * @param fourth 4th priority of direction to be returned 
+ *
+ * @see elm_ctxpopup_direction_priority_set for more information.
+ * 
+ * @ingroup Ctxpopup
+ */
+EAPI void
+elm_ctxpopup_direction_priority_get(Evas_Object *obj,
+                                    Elm_Ctxpopup_Direction *first,
+                                    Elm_Ctxpopup_Direction *second,
+                                    Elm_Ctxpopup_Direction *third,
+                                    Elm_Ctxpopup_Direction *fourth)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+      return;
+
+   if (first)
+      *first = wd->dir_priority[0];
+   if (second)
+      *second = wd->dir_priority[1];
+   if (third)
+      *third = wd->dir_priority[2];
+   if (fourth)
+      *fourth = wd->dir_priority[3];
+}
diff --git a/src/lib/elc_fileselector.c b/src/lib/elc_fileselector.c
new file mode 100644 (file)
index 0000000..2cf3010
--- /dev/null
@@ -0,0 +1,1052 @@
+/**
+ * @defgroup Fileselector Fileselector
+ *
+ * A fileselector is a widget that allows a user to navigate through a
+ * tree of files.  It contains buttons for Home(~) and Up(..) as well
+ * as cancel/ok buttons to confirm/cancel a selection.  This widget is
+ * currently very much in progress.
+ *
+ * TODO
+ * child elements focusing support
+ * userdefined icon/label cb
+ * show/hide/add buttons ???
+ * show/Hide hidden files
+ * double click to choose a file
+ * multiselection
+ * make variable/function names that are sensible
+ * Filter support
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * "selected" - the user clicks on a file
+ * "directory,open" - the list is populated with new content.
+ *                    event_info is a directory.
+ * "done" - the user clicks on the ok or cancel button
+ */
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *edje;
+   Evas_Object *filename_entry;
+   Evas_Object *path_entry;
+   Evas_Object *files_list;
+   Evas_Object *files_grid;
+   Evas_Object *up_button;
+   Evas_Object *home_button;
+
+   Evas_Object *ok_button;
+   Evas_Object *cancel_button;
+
+   const char  *path;
+   const char  *selection;
+   Ecore_Idler *sel_idler;
+
+   const char  *path_separator;
+
+   Elm_Fileselector_Mode mode;
+
+   Eina_Bool    only_folder : 1;
+   Eina_Bool    expand : 1;
+};
+
+struct sel_data
+{
+   Evas_Object *fs;
+   const char  *path;
+};
+
+Elm_Genlist_Item_Class list_itc;
+Elm_Gengrid_Item_Class grid_itc;
+
+static const char *widtype = NULL;
+
+static const char SIG_DIRECTORY_OPEN[] = "directory,open";
+static const char SIG_DONE[] = "done";
+static const char SIG_SELECTED[] = "selected";
+static const Evas_Smart_Cb_Description _signals[] = {
+   {SIG_DIRECTORY_OPEN, "s"},
+   {SIG_DONE, "s"},
+   {SIG_SELECTED, "s"},
+   {NULL, NULL}
+};
+
+static void _populate(Evas_Object      *obj,
+                      const char       *path,
+                      Elm_Genlist_Item *parent);
+static void _do_anchors(Evas_Object *obj,
+                        const char  *path);
+
+/***  ELEMENTARY WIDGET  ***/
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   void *sd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->path) eina_stringshare_del(wd->path);
+   if (wd->selection) eina_stringshare_del(wd->selection);
+   if (wd->sel_idler)
+     {
+        sd = ecore_idler_del(wd->sel_idler);
+        free(sd);
+     }
+   free(wd);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->edje, &minw, &minh, minw, minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *style = elm_widget_style_get(obj);
+   const char *data;
+   char buf[1024];
+
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->edje, "fileselector", "base", style);
+
+   if (elm_object_disabled_get(obj))
+     edje_object_signal_emit(wd->edje, "elm,state,disabled", "elm");
+
+   data = edje_object_data_get(wd->edje, "path_separator");
+   if (data)
+     wd->path_separator = data;
+   else
+     wd->path_separator = "/";
+
+   if (!style) style = "default";
+   snprintf(buf, sizeof(buf), "fileselector/%s", style);
+
+#define SWALLOW(part_name, object_ptn)                                \
+  if (object_ptn)                                                     \
+    {                                                                 \
+       elm_widget_style_set(object_ptn, buf);                         \
+       if (edje_object_part_swallow(wd->edje, part_name, object_ptn)) \
+         evas_object_show(object_ptn);                                \
+       else                                                           \
+         evas_object_hide(object_ptn);                                \
+    }
+   SWALLOW("elm.swallow.up", wd->up_button);
+   SWALLOW("elm.swallow.home", wd->home_button);
+
+   if (wd->mode == ELM_FILESELECTOR_LIST)
+     {
+        if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
+                                     wd->files_list))
+          {
+             evas_object_show(wd->files_list);
+             evas_object_hide(wd->files_grid);
+          }
+        else
+          evas_object_hide(wd->files_list);
+     }
+   else
+     {
+        if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
+                                     wd->files_grid))
+          {
+             evas_object_show(wd->files_grid);
+             evas_object_hide(wd->files_list);
+          }
+        else
+          evas_object_hide(wd->files_grid);
+     }
+
+   SWALLOW("elm.swallow.filename", wd->filename_entry);
+   SWALLOW("elm.swallow.path", wd->path_entry);
+
+   snprintf(buf, sizeof(buf), "fileselector/actions/%s", style);
+   SWALLOW("elm.swallow.cancel", wd->cancel_button);
+   SWALLOW("elm.swallow.ok", wd->ok_button);
+#undef SWALLOW
+
+   edje_object_message_signal_process(wd->edje);
+   edje_object_scale_set
+     (wd->edje, elm_widget_scale_get(obj) * _elm_config->scale);
+   _sizing_eval(obj);
+}
+
+/***  GENLIST "MODEL"  ***/
+static char *
+_itc_label_get(void              *data,
+               Evas_Object *obj   __UNUSED__,
+               const char *source __UNUSED__)
+{
+   return strdup(ecore_file_file_get(data)); /* NOTE this will be
+                                              * free() by the
+                                              * caller */
+}
+
+static Evas_Object *
+_itc_icon_get(void        *data,
+              Evas_Object *obj,
+              const char  *source)
+{
+   Evas_Object *ic;
+
+   if (!strcmp(source, "elm.swallow.icon"))
+     {
+        ic = elm_icon_add(obj);
+        if (ecore_file_is_dir((char *)data))
+          elm_icon_standard_set(ic, "folder");
+        else
+          elm_icon_standard_set(ic, "file");
+        evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL,
+                                         1, 1);
+        evas_object_show(ic);
+        return ic;
+     }
+   return NULL;
+}
+
+static Eina_Bool
+_itc_state_get(void *data         __UNUSED__,
+               Evas_Object *obj   __UNUSED__,
+               const char *source __UNUSED__)
+{
+   return EINA_FALSE;
+}
+
+static void
+_itc_del(void            *data,
+         Evas_Object *obj __UNUSED__)
+{
+   eina_stringshare_del(data);
+}
+
+static void
+_expand_done(void            *data,
+             Evas_Object *obj __UNUSED__,
+             void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   const char *path = elm_genlist_item_data_get(it);
+   _populate(data, path, it);
+}
+
+static void
+_contract_done(void *data       __UNUSED__,
+               Evas_Object *obj __UNUSED__,
+               void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_subitems_clear(it);
+}
+
+static void
+_expand_req(void *data       __UNUSED__,
+            Evas_Object *obj __UNUSED__,
+            void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 1);
+}
+
+static void
+_contract_req(void *data       __UNUSED__,
+              Evas_Object *obj __UNUSED__,
+              void            *event_info)
+{
+   Elm_Genlist_Item *it = event_info;
+   elm_genlist_item_expanded_set(it, 0);
+}
+
+/***  PRIVATES  ***/
+static Eina_Bool
+_sel_do(void *data)
+{
+   struct sel_data *sd;
+   const char *path;
+   Widget_Data *wd;
+   const char *p;
+
+   sd = data;
+   wd = elm_widget_data_get(sd->fs);
+   path = sd->path;
+
+   if ((!wd->only_folder) && ecore_file_is_dir(path))
+     {
+        if (wd->expand && wd->mode == ELM_FILESELECTOR_LIST)
+          {
+             _do_anchors(sd->fs, path);
+             elm_scrolled_entry_entry_set(wd->filename_entry, "");
+          }
+        else
+          {
+             /* keep a ref to path 'couse it will be destroyed by _populate */
+             p = eina_stringshare_add(path);
+             _populate(sd->fs, p, NULL);
+             eina_stringshare_del(p);
+          }
+        goto end;
+     }
+   else /* navigating through folders only or file is not a dir. */
+     {
+        if (wd->expand && wd->mode == ELM_FILESELECTOR_LIST)
+          _do_anchors(sd->fs, path);
+        else if (wd->only_folder)
+          {
+             /* keep a ref to path 'couse it will be destroyed by _populate */
+             p = eina_stringshare_add(path);
+             _populate(sd->fs, p, NULL);
+             eina_stringshare_del(p);
+          }
+        elm_scrolled_entry_entry_set(wd->filename_entry,
+                                     ecore_file_file_get(path));
+     }
+
+   evas_object_smart_callback_call(sd->fs, SIG_SELECTED, (void *)path);
+
+end:
+   wd->sel_idler = NULL;
+   free(sd);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_sel(void            *data,
+     Evas_Object *obj __UNUSED__,
+     void            *event_info)
+{
+   struct sel_data *sd;
+   Widget_Data *wd;
+   void *old_sd;
+   char *dir;
+
+   wd = elm_widget_data_get(data);
+   if (!wd) return;
+
+   sd = malloc(sizeof(*sd));
+   sd->fs = data;
+   sd->path = wd->mode == ELM_FILESELECTOR_LIST ?
+       elm_genlist_item_data_get(event_info) :
+       elm_gengrid_item_data_get(event_info);
+
+   if (!sd->path)
+     {
+        eina_stringshare_replace(&wd->path, "");
+        goto end;
+     }
+
+   dir = wd->only_folder ? strdup(sd->path) : ecore_file_dir_get(sd->path);
+   if (dir)
+     {
+        eina_stringshare_replace(&wd->path, dir);
+        free(dir);
+     }
+   else
+     {
+        eina_stringshare_replace(&wd->path, "");
+     }
+
+end:
+   if (wd->sel_idler)
+     {
+        old_sd = ecore_idler_del(wd->sel_idler);
+        free(old_sd);
+     }
+   wd->sel_idler = ecore_idler_add(_sel_do, sd);
+}
+
+static void
+_up(void            *data,
+    Evas_Object *obj __UNUSED__,
+    void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   char *parent;
+
+   Widget_Data *wd = elm_widget_data_get(fs);
+   if (!wd) return;
+   parent = ecore_file_dir_get(wd->path);
+   _populate(fs, parent, NULL);
+   free(parent);
+}
+
+static void
+_home(void            *data,
+      Evas_Object *obj __UNUSED__,
+      void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   _populate(fs, getenv("HOME"), NULL);
+}
+
+static void
+_ok(void            *data,
+    Evas_Object *obj __UNUSED__,
+    void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   evas_object_smart_callback_call(fs, SIG_DONE,
+                                   (void *)elm_fileselector_selected_get(fs));
+}
+
+static void
+_canc(void            *data,
+      Evas_Object *obj __UNUSED__,
+      void *event_info __UNUSED__)
+{
+   Evas_Object *fs = data;
+   evas_object_smart_callback_call(fs, SIG_DONE, NULL);
+}
+
+static void
+_anchor_clicked(void            *data,
+                Evas_Object *obj __UNUSED__,
+                void            *event_info)
+{
+   Evas_Object *fs = data;
+   Widget_Data *wd = elm_widget_data_get(fs);
+   Elm_Entry_Anchor_Info *info = event_info;
+   const char *p;
+   if (!wd) return;
+   // keep a ref to path 'couse it will be destroyed by _populate
+   p = eina_stringshare_add(info->name);
+   _populate(fs, p, NULL);
+   evas_object_smart_callback_call(data, SIG_SELECTED, (void *)p);
+   eina_stringshare_del(p);
+}
+
+static void
+_do_anchors(Evas_Object *obj,
+            const char  *path)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char **tok, buf[PATH_MAX * 3];
+   int i, j;
+   if (!wd) return;
+   buf[0] = '\0';
+   tok = eina_str_split(path, "/", 0);
+   eina_strlcat(buf, "<a href=/>root</a>", sizeof(buf));
+   for (i = 0; tok[i]; i++)
+     {
+        if ((!tok[i]) || (!tok[i][0])) continue;
+        eina_strlcat(buf, wd->path_separator, sizeof(buf));
+        eina_strlcat(buf, "<a href=", sizeof(buf));
+        for (j = 0; j <= i; j++)
+          {
+             if (strlen(tok[j]) < 1) continue;
+             eina_strlcat(buf, "/", sizeof(buf));
+             eina_strlcat(buf, tok[j], sizeof(buf));
+          }
+        eina_strlcat(buf, ">", sizeof(buf));
+        eina_strlcat(buf, tok[i], sizeof(buf));
+        eina_strlcat(buf, "</a>", sizeof(buf));
+     }
+   free(tok[0]);
+   free(tok);
+
+   elm_scrolled_entry_entry_set(wd->path_entry, buf);
+}
+
+static void
+_populate(Evas_Object      *obj,
+          const char       *path,
+          Elm_Genlist_Item *parent)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   DIR *dir;
+   struct dirent *dp;
+   char buf[PATH_MAX];
+   char *real;
+   Eina_List *files = NULL, *dirs = NULL, *l;
+
+   if ((!wd) || (!ecore_file_is_dir(path))) return;
+   dir = opendir(path);
+   if (!dir) return;
+   evas_object_smart_callback_call(obj, SIG_DIRECTORY_OPEN, (void *)path);
+   if (!parent)
+     {
+        elm_genlist_clear(wd->files_list);
+        elm_gengrid_clear(wd->files_grid);
+        eina_stringshare_replace(&wd->path, path);
+        _do_anchors(obj, path);
+     }
+
+   if (wd->filename_entry) elm_scrolled_entry_entry_set(wd->filename_entry, "");
+   while ((dp = readdir(dir)))
+     {
+        if (dp->d_name[0] == '.') continue;  // TODO make this configurable
+
+        snprintf(buf, sizeof(buf), "%s/%s", path, dp->d_name);
+        real = ecore_file_realpath(buf); /* TODO: this will resolv
+                                          * symlinks...I dont like
+                                          * it*/
+        if (ecore_file_is_dir(real))
+          dirs = eina_list_append(dirs, real);
+        else if (!wd->only_folder)
+          files = eina_list_append(files, real);
+     }
+   closedir(dir);
+
+   files = eina_list_sort(files, eina_list_count(files),
+                          EINA_COMPARE_CB(strcoll));
+   dirs = eina_list_sort(dirs, eina_list_count(dirs), EINA_COMPARE_CB(strcoll));
+   EINA_LIST_FOREACH(dirs, l, real)
+     {
+        if (wd->mode == ELM_FILESELECTOR_LIST)
+          elm_genlist_item_append(wd->files_list, &list_itc,
+                                  eina_stringshare_add(real), /* item data */
+                                  parent,
+                                  wd->expand ? ELM_GENLIST_ITEM_SUBITEMS :
+                                  ELM_GENLIST_ITEM_NONE,
+                                  NULL, NULL);
+        else if (wd->mode == ELM_FILESELECTOR_GRID)
+          elm_gengrid_item_append(wd->files_grid, &grid_itc,
+                                  eina_stringshare_add(real), /* item data */
+                                  NULL, NULL);
+
+        free(real);
+     }
+   eina_list_free(dirs);
+
+   EINA_LIST_FOREACH(files, l, real)
+     {
+        if (wd->mode == ELM_FILESELECTOR_LIST)
+          elm_genlist_item_append(wd->files_list, &list_itc,
+                                  eina_stringshare_add(real), /* item data */
+                                  parent, ELM_GENLIST_ITEM_NONE,
+                                  NULL, NULL);
+        else if (wd->mode == ELM_FILESELECTOR_GRID)
+          elm_gengrid_item_append(wd->files_grid, &grid_itc,
+                                  eina_stringshare_add(real), /* item data */
+                                  NULL, NULL);
+        free(real);
+     }
+   eina_list_free(files);
+}
+
+/***  API  ***/
+
+/**
+ * Add a new Fileselector object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Fileselector
+ */
+EAPI Evas_Object *
+elm_fileselector_add(Evas_Object *parent)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   Evas *e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   Evas_Object *obj, *ic, *bt, *li, *en, *grid;
+   Widget_Data *wd;
+   int s;
+
+   // Elementary Widget
+   wd = ELM_NEW(Widget_Data);
+   wd->expand = !!_elm_config->fileselector_expand_enable;
+   obj = elm_widget_add(evas_object_evas_get(parent));
+   ELM_SET_WIDTYPE(widtype, "fileselector");
+   elm_widget_type_set(obj, "fileselector");
+   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, EINA_FALSE);
+
+   wd->edje = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->edje, "fileselector", "base", "default");
+   elm_widget_resize_object_set(obj, wd->edje);
+
+   // up btn
+   ic = elm_icon_add(parent);
+   elm_icon_standard_set(ic, "arrow_up");
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   bt = elm_button_add(parent);
+   elm_button_icon_set(bt, ic);
+   elm_button_label_set(bt, "Up");
+   evas_object_size_hint_align_set(bt, 0.0, 0.0);
+
+   evas_object_smart_callback_add(bt, "clicked", _up, obj);
+
+   elm_widget_sub_object_add(obj, bt);
+   wd->up_button = bt;
+
+   // home btn
+   ic = elm_icon_add(parent);
+   elm_icon_standard_set(ic, "home");
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   bt = elm_button_add(parent);
+   elm_button_icon_set(bt, ic);
+   elm_button_label_set(bt, "Home");
+   evas_object_size_hint_align_set(bt, 0.0, 0.0);
+
+   evas_object_smart_callback_add(bt, "clicked", _home, obj);
+
+   elm_widget_sub_object_add(obj, bt);
+   wd->home_button = bt;
+
+   list_itc.item_style = grid_itc.item_style = "default";
+   list_itc.func.label_get = grid_itc.func.label_get = _itc_label_get;
+   list_itc.func.icon_get = grid_itc.func.icon_get = _itc_icon_get;
+   list_itc.func.state_get = grid_itc.func.state_get = _itc_state_get;
+   list_itc.func.del = grid_itc.func.del = _itc_del;
+
+   li = elm_genlist_add(parent);
+   evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_min_set(li, 100, 100);
+
+   grid = elm_gengrid_add(parent);
+   evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+   s = elm_finger_size_get() * 2;
+   elm_gengrid_item_size_set(grid, s, s);
+   elm_gengrid_align_set(grid, 0.0, 0.0);
+
+   evas_object_smart_callback_add(li, "selected", _sel, obj);
+   evas_object_smart_callback_add(li, "expand,request", _expand_req, obj);
+   evas_object_smart_callback_add(li, "contract,request", _contract_req, obj);
+   evas_object_smart_callback_add(li, "expanded", _expand_done, obj);
+   evas_object_smart_callback_add(li, "contracted", _contract_done, obj);
+
+   evas_object_smart_callback_add(grid, "selected", _sel, obj);
+
+   elm_widget_sub_object_add(obj, li);
+   elm_widget_sub_object_add(obj, grid);
+   wd->files_list = li;
+   wd->files_grid = grid;
+
+   // path entry
+   en = elm_scrolled_entry_add(parent);
+   elm_scrolled_entry_editable_set(en, EINA_FALSE);
+   elm_scrolled_entry_single_line_set(en, EINA_TRUE);
+   elm_scrolled_entry_line_char_wrap_set(en, EINA_TRUE);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   evas_object_smart_callback_add(en, "anchor,clicked", _anchor_clicked, obj);
+
+   elm_widget_sub_object_add(obj, en);
+   wd->path_entry = en;
+
+   // filename entry
+   en = elm_scrolled_entry_add(parent);
+   elm_scrolled_entry_editable_set(en, EINA_TRUE);
+   elm_scrolled_entry_single_line_set(en, EINA_TRUE);
+   elm_scrolled_entry_line_char_wrap_set(en, EINA_TRUE);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   elm_widget_sub_object_add(obj, en);
+   wd->filename_entry = en;
+
+   elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE);
+   elm_fileselector_is_save_set(obj, EINA_FALSE);
+
+   _theme_hook(obj);
+
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * This enables/disables the file name entry box where the user can
+ * type in a name for the file to be saved as.
+ *
+ * @param obj The fileselector object
+ * @param is_save If true, the fileselector is a save dialog
+ *
+ * @ingroup Fileselector
+ */
+EAPI void
+elm_fileselector_is_save_set(Evas_Object *obj,
+                             Eina_Bool    is_save)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   elm_object_disabled_set(wd->filename_entry, is_save);
+
+   if (is_save)
+     edje_object_signal_emit(wd->edje, "elm,state,save,on", "elm");
+   else
+     edje_object_signal_emit(wd->edje, "elm,state,save,off", "elm");
+}
+
+/**
+ * This returns whether the fileselector is a "save" type fileselector
+ *
+ * @param obj The fileselector object
+ * @return If true, the fileselector is a save type.
+ *
+ * @ingroup Fileselector
+ */
+EAPI Eina_Bool
+elm_fileselector_is_save_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 elm_object_disabled_get(wd->filename_entry);
+}
+
+/**
+ * This enables/disables folder-only view in the fileselector.
+ *
+ * @param obj The fileselector object
+ * @param only If true, the fileselector will only display directories.
+ * If false, files are displayed also.
+ *
+ * @ingroup Fileselector
+ */
+EAPI void
+elm_fileselector_folder_only_set(Evas_Object *obj,
+                                 Eina_Bool    only)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->only_folder == only) return;
+   wd->only_folder = !!only;
+   if (wd->path) _populate(obj, wd->path, NULL);
+}
+
+/**
+ * This gets the state of file display in the fileselector.
+ *
+ * @param obj The fileselector object
+ * @return If true, files are not being shown in the fileselector.
+ * If false, files are being shown.
+ *
+ * @ingroup Fileselector
+ */
+EAPI Eina_Bool
+elm_fileselector_folder_only_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->only_folder;
+}
+
+/**
+ * This enables/disables the ok,cancel buttons.
+ *
+ * @param obj The fileselector object
+ * @param only If true, a box containing ok and cancel buttons is created.
+ * If false, the box and the buttons are destroyed.
+ *
+ * @ingroup Fileselector
+ */
+EAPI void
+elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj,
+                                       Eina_Bool    visible)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *bt;
+   if (!wd) return;
+
+   if (visible)
+     {
+        // cancel btn
+        bt = elm_button_add(obj);
+        elm_button_label_set(bt, "Cancel");
+
+        evas_object_smart_callback_add(bt, "clicked", _canc, obj);
+
+        elm_widget_sub_object_add(obj, bt);
+        wd->cancel_button = bt;
+
+        // ok btn
+        bt = elm_button_add(obj);
+        elm_button_label_set(bt, "OK");
+
+        evas_object_smart_callback_add(bt, "clicked", _ok, obj);
+
+        elm_widget_sub_object_add(obj, bt);
+        wd->ok_button = bt;
+
+        _theme_hook(obj);
+     }
+   else
+     {
+        evas_object_del(wd->cancel_button);
+        wd->cancel_button = NULL;
+        evas_object_del(wd->ok_button);
+        wd->ok_button = NULL;
+     }
+}
+
+/**
+ * This gets the state of the box containing ok and cancel buttons.
+ *
+ * @param obj The fileselector object
+ * @return If true, the box exists.
+ * If false, the box does not exist.
+ *
+ * @ingroup Fileselector
+ */
+EAPI Eina_Bool
+elm_fileselector_buttons_ok_cancel_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->ok_button ? EINA_TRUE : EINA_FALSE;
+}
+
+/**
+ * This enables a tree view in the fileselector, <b>if in @c
+ * ELM_FILESELECTOR_LIST mode</b>. If it's in other mode, the changes
+ * made by this function will only be visible when one switches back
+ * to list mode.
+ *
+ * @param obj The fileselector object
+ * @param expand If true, tree view is enabled.
+ * If false, tree view is disabled.
+ *
+ * In a tree view, arrows are created on the sides of directories,
+ * allowing them to expand in place.
+ *
+ * @ingroup Fileselector
+ */
+EAPI void
+elm_fileselector_expandable_set(Evas_Object *obj,
+                                Eina_Bool    expand)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   wd->expand = !!expand;
+
+   if (wd->path) _populate(obj, wd->path, NULL);
+}
+
+/**
+ * This gets the state of tree view in the fileselector.
+ *
+ * @param obj The fileselector object
+ * @return If true, tree view is enabled and folders will be expandable.
+ * If false, tree view is disabled.
+ *
+ * @ingroup Fileselector
+ */
+EAPI Eina_Bool
+elm_fileselector_expandable_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->expand;
+}
+
+/**
+ * This sets the path that the fileselector will display.
+ *
+ * @param obj The fileselector object
+ * @param path The path of the fileselector
+ *
+ * @ingroup Fileselector
+ */
+EAPI void
+elm_fileselector_path_set(Evas_Object *obj,
+                          const char  *path)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   _populate(obj, path, NULL);
+}
+
+/**
+ * This gets the path that the fileselector displays.
+ *
+ * @param obj The fileselector object
+ * @return The path that the fileselector is displaying
+ *
+ * @ingroup Fileselector
+ */
+EAPI const char *
+elm_fileselector_path_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->path;
+}
+
+/**
+ * This sets the mode in which the fileselector will display files.
+ *
+ * @param obj The fileselector object
+
+ * @param mode The mode of the fileselector, being it one of @c
+ * ELM_FILESELECTOR_LIST (default) or @c ELM_FILESELECTOR_GRID. The
+ * first one, naturally, will display the files in a list. By using
+ * elm_fileselector_expandable_set(), the user will trigger a tree
+ * view for that list. The latter will make the widget to display its
+ * entries in a grid form.
+ *
+ * @see elm_fileselector_expandable_set().
+ *
+ * @ingroup Fileselector
+ */
+EAPI void
+elm_fileselector_mode_set(Evas_Object          *obj,
+                          Elm_Fileselector_Mode mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (mode == wd->mode) return;
+
+   if (mode == ELM_FILESELECTOR_LIST)
+     {
+        if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
+                                     wd->files_list))
+          {
+             evas_object_show(wd->files_list);
+             evas_object_hide(wd->files_grid);
+          }
+        else
+          evas_object_hide(wd->files_list);
+     }
+   else
+     {
+        if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
+                                     wd->files_grid))
+          {
+             evas_object_show(wd->files_grid);
+             evas_object_hide(wd->files_list);
+          }
+        else
+          evas_object_hide(wd->files_grid);
+     }
+
+   wd->mode = mode;
+
+   _populate(obj, wd->path, NULL);
+}
+
+/**
+ * This gets the mode in which the fileselector is displaying files.
+ *
+ * @param obj The fileselector object
+ * @return The mode in which the fileselector is at
+ *
+ * @ingroup Fileselector
+ */
+EAPI Elm_Fileselector_Mode
+elm_fileselector_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_FILESELECTOR_LAST;
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_FILESELECTOR_LAST;
+
+   return wd->mode;
+}
+
+/**
+ * This gets the currently selected path in the file selector.
+ *
+ * @param obj The file selector object
+ * @return The absolute path of the selected object in the fileselector
+ *
+ * @ingroup Fileselector
+ */
+EAPI const char *
+elm_fileselector_selected_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->filename_entry)
+     {
+        const char *name;
+        char buf[PATH_MAX];
+
+        name = elm_scrolled_entry_entry_get(wd->filename_entry);
+        snprintf(buf, sizeof(buf), "%s/%s",
+                 wd->only_folder ? ecore_file_dir_get(wd->path) : wd->path,
+                 name);
+        eina_stringshare_replace(&wd->selection, buf);
+        return wd->selection;
+     }
+
+   if (wd->mode == ELM_FILESELECTOR_LIST)
+     {
+        Elm_Genlist_Item *it;
+        it = elm_genlist_selected_item_get(wd->files_list);
+        if (it) return elm_genlist_item_data_get(it);
+     }
+   else
+     {
+        Elm_Gengrid_Item *it;
+        it = elm_gengrid_selected_item_get(wd->files_grid);
+        if (it) return elm_gengrid_item_data_get(it);
+     }
+
+   return wd->path;
+}
+
+/**
+ * This sets the currently selected path in the file selector.
+ *
+ * @param obj The file selector object
+ * @param path The path to a file or directory
+ * @return @c EINA_TRUE on success, @c EINA_FALSE on failure. The
+ * latter case occurs if the directory or file pointed to do not
+ * exist.
+ *
+ * @ingroup Fileselector
+ */
+EAPI Eina_Bool
+elm_fileselector_selected_set(Evas_Object *obj,
+                              const char  *path)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+
+   if (ecore_file_is_dir(path))
+     _populate(obj, path, NULL);
+   else
+     {
+        if (!ecore_file_exists(path))
+          return EINA_FALSE;
+
+        _populate(obj, ecore_file_dir_get(path), NULL);
+        if (wd->filename_entry)
+          {
+             elm_scrolled_entry_entry_set(wd->filename_entry,
+                                          ecore_file_file_get(path));
+             eina_stringshare_replace(&wd->selection, path);
+          }
+     }
+
+   return EINA_TRUE;
+}
+
diff --git a/src/lib/elc_fileselector_button.c b/src/lib/elc_fileselector_button.c
new file mode 100644 (file)
index 0000000..dbdeeb2
--- /dev/null
@@ -0,0 +1,683 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup File_Selector_Button File Selector Button
+ *
+ * A button that, when clicked, creates an Elementary window (or inner
+ * window) with an Elementary File Selector within. When a file is
+ * chosen, the (inner) window is closed and the selected file is
+ * exposed as an evas_object_smart_callback_call() of the button.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *self, *btn, *fs, *fsw;
+   const char  *window_title;
+   Evas_Coord   w, h;
+   struct
+   {
+      const char *path;
+      Eina_Bool   expandable : 1;
+      Eina_Bool   folder_only : 1;
+      Eina_Bool   is_save : 1;
+   } fsd;
+   Eina_Bool inwin_mode : 1;
+};
+
+#define DEFAULT_WINDOW_TITLE "Select a file"
+
+static const char *widtype = NULL;
+
+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 _changed_size_hints(void        *data,
+                                Evas        *e,
+                                Evas_Object *obj,
+                                void        *event_info);
+static void _on_focus_hook(void        *data,
+                           Evas_Object *obj);
+static void _selection_done(void        *data,
+                            Evas_Object *obj,
+                            void        *event_info);
+static void _activate(Widget_Data *wd);
+
+static const char SIG_FILE_CHOSEN[] = "file,chosen";
+static const Evas_Smart_Cb_Description _signals[] = {
+   {SIG_FILE_CHOSEN, "s"},
+   {NULL, NULL}
+};
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Evas_Object *win;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->window_title) eina_stringshare_del(wd->window_title);
+   if (wd->fsd.path) eina_stringshare_del(wd->fsd.path);
+   if (wd->fs)
+     {
+        win = evas_object_data_del(obj, "win");
+        evas_object_del(win);
+     }
+   free(wd);
+}
+
+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->btn);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char buf[4096];
+   if (!wd) return;
+   snprintf(buf, sizeof(buf), "fileselector_button/%s",
+            elm_widget_style_get(obj));
+   elm_object_style_set(wd->btn, buf);
+   _sizing_eval(obj);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_disabled_set(wd->btn, elm_widget_disabled_get(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_min_get(wd->btn, &minw, &minh);
+   evas_object_size_hint_max_get(wd->btn, &maxw, &maxh);
+   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
+_activate_hook(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _activate(wd);
+}
+
+static void
+_button_clicked(void            *data,
+                Evas_Object *obj __UNUSED__,
+                void *event_info __UNUSED__)
+{
+   _activate(data);
+}
+
+static Evas_Object *
+_parent_win_get(Evas_Object *obj)
+{
+   while ((obj) && (strcmp(elm_widget_type_get(obj), "win")))
+     obj = elm_object_parent_widget_get(obj);
+
+   return obj;
+}
+
+static Evas_Object *
+_new_window_add(Widget_Data *wd)
+{
+   Evas_Object *win, *bg;
+
+   win = elm_win_add(NULL, "fileselector_button", ELM_WIN_DIALOG_BASIC);
+   elm_win_title_set(win, wd->window_title);
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   evas_object_resize(win, wd->w, wd->h);
+   return win;
+}
+
+static void
+_activate(Widget_Data *wd)
+{
+   Eina_Bool is_inwin = EINA_FALSE;
+
+   if (wd->fs) return;
+
+   if (wd->inwin_mode)
+     {
+        wd->fsw = _parent_win_get(wd->self);
+
+        if (!wd->fsw)
+          wd->fsw = _new_window_add(wd);
+        else
+          {
+             wd->fsw = elm_win_inwin_add(wd->fsw);
+             is_inwin = EINA_TRUE;
+          }
+     }
+   else
+     wd->fsw = _new_window_add(wd);
+
+   wd->fs = elm_fileselector_add(wd->fsw);
+   elm_fileselector_expandable_set(wd->fs, wd->fsd.expandable);
+   elm_fileselector_folder_only_set(wd->fs, wd->fsd.folder_only);
+   elm_fileselector_is_save_set(wd->fs, wd->fsd.is_save);
+   elm_fileselector_selected_set(wd->fs, wd->fsd.path);
+   evas_object_size_hint_weight_set(wd->fs, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(wd->fs, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(wd->fs, "done", _selection_done, wd);
+   evas_object_show(wd->fs);
+
+   if (is_inwin)
+     {
+        elm_win_inwin_content_set(wd->fsw, wd->fs);
+        elm_win_inwin_activate(wd->fsw);
+     }
+   else
+     {
+        elm_win_resize_object_add(wd->fsw, wd->fs);
+        evas_object_show(wd->fsw);
+     }
+}
+
+static void
+_selection_done(void            *data,
+                Evas_Object *obj __UNUSED__,
+                void            *event_info)
+{
+   const char *file = event_info;
+   Widget_Data *wd = data;
+   Evas_Object *del;
+   if (!wd) return;
+
+   if (file) eina_stringshare_replace(&wd->fsd.path, file);
+
+   del = wd->fsw;
+   wd->fs = NULL;
+   wd->fsw = NULL;
+   evas_object_del(del);
+
+   evas_object_smart_callback_call(wd->self, SIG_FILE_CHOSEN,
+                                   (void *)wd->fsd.path);
+}
+
+/**
+ * Add a new file selector button into the parent object.
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI Evas_Object *
+elm_fileselector_button_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   wd->window_title = eina_stringshare_add(DEFAULT_WINDOW_TITLE);
+   wd->fsd.path = eina_stringshare_add(getenv("HOME"));
+   wd->fsd.expandable = _elm_config->fileselector_expand_enable;
+   wd->inwin_mode = _elm_config->inwin_dialogs_enable;
+   wd->w = 400;
+   wd->h = 400;
+
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "fileselector_button");
+   elm_widget_type_set(obj, "fileselector_button");
+   elm_widget_sub_object_add(parent, obj);
+   wd->self = 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_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_activate_hook_set(obj, _activate_hook);
+
+   wd->btn = elm_button_add(parent);
+   elm_widget_resize_object_set(obj, wd->btn);
+   evas_object_event_callback_add(wd->btn, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                  _changed_size_hints, obj);
+   evas_object_smart_callback_add(wd->btn, "clicked", _button_clicked, wd);
+   elm_widget_sub_object_add(obj, wd->btn);
+
+   _theme_hook(obj);
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the label used in the file selector button.
+ *
+ * @param obj The button object
+ * @param label The text label text to be displayed on the button
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_label_set(Evas_Object *obj,
+                                  const char  *label)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_button_label_set(wd->btn, label);
+}
+
+/**
+ * Get the label used in the file selector button.
+ *
+ * @param obj The button object
+ * @return The button label
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI const char *
+elm_fileselector_button_label_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_button_label_get(wd->btn);
+}
+
+/**
+ * Set the title of the file selector button's window.
+ *
+ * @param obj The button object
+ * @param title The title string
+ *
+ * Note that it will only take any effect if the fileselector button
+ * not at "inwin mode".
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_window_title_set(Evas_Object *obj,
+                                         const char  *title)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   eina_stringshare_replace(&wd->window_title, title);
+
+   if (wd->fsw)
+     elm_win_title_set(wd->fsw, wd->window_title);
+}
+
+/**
+ * Get the title of the file selector button's window.
+ *
+ * @param obj The button object
+ * @return Title of the file selector button's window
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI const char *
+elm_fileselector_button_window_title_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->window_title;
+}
+
+/**
+ * Set the size of the file selector button's window.
+ *
+ * @param obj The button object
+ * @param width The width
+ * @param height The height
+ *
+ * Note that it will only take any effect if the fileselector button not at
+ * "inwin mode". Default size for the window (when applicable) is 400x400.
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_window_size_set(Evas_Object *obj,
+                                        Evas_Coord   width,
+                                        Evas_Coord   height)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->w = width;
+   wd->h = height;
+
+   if (wd->fsw)
+     evas_object_resize(wd->fsw, wd->w, wd->h);
+}
+
+/**
+ * Get the size of the file selector button's window.
+ *
+ * @param obj The button object
+ * @param width Pointer into which to store the width value
+ * @param height Pointer into which to store the height value
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_window_size_get(const Evas_Object *obj,
+                                        Evas_Coord        *width,
+                                        Evas_Coord        *height)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   if (width) *width = wd->w;
+   if (height) *height = wd->h;
+}
+
+/**
+ * Set the starting path of the file selector button's window.
+ *
+ * @param obj The button object
+ * @param path The path string
+ *
+ * It must be a <b>directory</b> path.
+ * Default path is "HOME" environment variable's value.
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_path_set(Evas_Object *obj,
+                                 const char  *path)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   eina_stringshare_replace(&wd->fsd.path, path);
+
+   if (wd->fs)
+     elm_fileselector_selected_set(wd->fs, wd->fsd.path);
+}
+
+/**
+ * Get the <b>last</b> path of the file selector button's window.
+ *
+ * @param obj The button object
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI const char *
+elm_fileselector_button_path_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->fsd.path;
+}
+
+/**
+ * Set whether the button's file selector is to present itself as an
+ * Elementary Generic List (which will expand its entries for nested
+ * directories) or as canonical list, which will be rendered again
+ * with the contents of each selected directory.
+ *
+ * @param obj The button object
+ * @param value The expandable flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_expandable_set(Evas_Object *obj,
+                                       Eina_Bool    value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->fsd.expandable = value;
+
+   if (wd->fs)
+     elm_fileselector_expandable_set(wd->fs, wd->fsd.expandable);
+}
+
+/**
+ * Get the button's file selector expandable flag.
+ *
+ * @param obj The button object
+ * @return value The expandable flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI Eina_Bool
+elm_fileselector_button_expandable_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->fsd.expandable;
+}
+
+/**
+ * Set whether the button's file selector list is to display folders
+ * only or the directory contents, as well.
+ *
+ * @param obj The button object
+ * @param value The "folder only" flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_folder_only_set(Evas_Object *obj,
+                                        Eina_Bool    value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->fsd.folder_only = value;
+
+   if (wd->fs)
+     elm_fileselector_folder_only_set(wd->fs, wd->fsd.folder_only);
+}
+
+/**
+ * Get the button's file selector "folder only" flag.
+ *
+ * @param obj The button object
+ * @return value The "folder only" flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI Eina_Bool
+elm_fileselector_button_folder_only_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->fsd.folder_only;
+}
+
+/**
+ * Set whether the button's file selector has an editable text entry
+ * which will hold its current selection.
+ *
+ * @param obj The button object
+ * @param value The "is save" flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_is_save_set(Evas_Object *obj,
+                                    Eina_Bool    value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->fsd.is_save = value;
+
+   if (wd->fs)
+     elm_fileselector_is_save_set(wd->fs, wd->fsd.is_save);
+}
+
+/**
+ * Get the button's file selector "is save" flag.
+ *
+ * @param obj The button object
+ * @return value The "is save" flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI Eina_Bool
+elm_fileselector_button_is_save_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->fsd.is_save;
+}
+
+/**
+ * Set whether the button's file selector will raise an Elementary
+ * Inner Window, instead of a dedicated Elementary Window. By default,
+ * it won't.
+ *
+ * @param obj The button object
+ * @param value The "inwin mode" flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_inwin_mode_set(Evas_Object *obj,
+                                       Eina_Bool    value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->inwin_mode = value;
+}
+
+/**
+ * Get the button's file selector "inwin mode" flag.
+ *
+ * @param obj The button object
+ * @return value The "inwin mode" flag
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI Eina_Bool
+elm_fileselector_button_inwin_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->inwin_mode;
+}
+
+/**
+ * Set the icon used for the button
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_fileselector_button_icon_unset() function.
+ *
+ * @param obj The button object
+ * @param icon  The icon object for the button
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI void
+elm_fileselector_button_icon_set(Evas_Object *obj,
+                                 Evas_Object *icon)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     {
+        evas_object_del(icon);
+        return;
+     }
+   elm_button_icon_set(wd->btn, icon);
+}
+
+/**
+ * Get the icon used for the button
+ *
+ * @param obj The button object
+ * @return The icon object that is being used
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI Evas_Object *
+elm_fileselector_button_icon_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_button_icon_get(wd->btn);
+}
+
+/**
+ * Unset the icon used for the button
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The button object
+ * @return The icon object that was being used
+ *
+ * @ingroup File_Selector_Button
+ */
+EAPI Evas_Object *
+elm_fileselector_button_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_button_icon_unset(wd->btn);
+}
+
diff --git a/src/lib/elc_fileselector_entry.c b/src/lib/elc_fileselector_entry.c
new file mode 100644 (file)
index 0000000..7b0ad6d
--- /dev/null
@@ -0,0 +1,655 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+ /**
+ * @defgroup File_Selector_Entry File Selector Entry
+ *
+ * An entry that shows to enter/display path and have an associated
+ * button to allow selecting the file from a dialog.
+ *
+ * The button, when clicked, creates an Elementary window (or inner
+ * window) with an Elementary File Selector within. When a file is
+ * chosen, the (inner) window is closed and the selected file is
+ * exposed as an evas_object_smart_callback_call() of the button.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *edje;
+   Evas_Object *button;
+   Evas_Object *entry;
+};
+
+static const char *widtype = NULL;
+
+static const char SIG_CHANGED[] = "changed";
+static const char SIG_ACTIVATED[] = "activated";
+static const char SIG_PRESS[] = "press";
+static const char SIG_LONGPRESSED[] = "longpressed";
+static const char SIG_CLICKED[] = "clicked";
+static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
+static const char SIG_FOCUSED[] = "focused";
+static const char SIG_UNFOCUSED[] = "unfocused";
+static const char SIG_SELECTION_PASTE[] = "selection,paste";
+static const char SIG_SELECTION_COPY[] = "selection,copy";
+static const char SIG_SELECTION_CUT[] = "selection,cut";
+static const char SIG_UNPRESSED[] = "unpressed";
+static const char SIG_FILE_CHOSEN[] = "file,chosen";
+static const Evas_Smart_Cb_Description _signals[] =
+{
+  {SIG_CHANGED, ""},
+  {SIG_ACTIVATED, ""},
+  {SIG_PRESS, ""},
+  {SIG_LONGPRESSED, ""},
+  {SIG_CLICKED, ""},
+  {SIG_CLICKED_DOUBLE, ""},
+  {SIG_FOCUSED, ""},
+  {SIG_UNFOCUSED, ""},
+  {SIG_SELECTION_PASTE, ""},
+  {SIG_SELECTION_COPY, ""},
+  {SIG_SELECTION_CUT, ""},
+  {SIG_UNPRESSED, ""},
+  {SIG_FILE_CHOSEN, "s"},
+  {NULL, NULL}
+};
+
+#define SIG_FWD(name)                                                    \
+static void                                                              \
+_##name##_fwd(void *data, Evas_Object *obj __UNUSED__, void *event_info) \
+{                                                                        \
+   evas_object_smart_callback_call(data, SIG_##name, event_info);        \
+}
+SIG_FWD(CHANGED)
+SIG_FWD(PRESS)
+SIG_FWD(LONGPRESSED)
+SIG_FWD(CLICKED)
+SIG_FWD(CLICKED_DOUBLE)
+SIG_FWD(FOCUSED)
+SIG_FWD(UNFOCUSED)
+SIG_FWD(SELECTION_PASTE)
+SIG_FWD(SELECTION_COPY)
+SIG_FWD(SELECTION_CUT)
+SIG_FWD(UNPRESSED)
+#undef SIG_FWD
+
+static void
+_FILE_CHOSEN_fwd(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   const char *file = event_info;
+   elm_scrolled_entry_entry_set(wd->entry, file);
+   evas_object_smart_callback_call(data, SIG_FILE_CHOSEN, event_info);
+}
+
+static void
+_ACTIVATED_fwd(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   const char *file = elm_scrolled_entry_entry_get(wd->entry);
+   elm_fileselector_button_path_set(wd->button, file);
+   evas_object_smart_callback_call(data, SIG_ACTIVATED, event_info);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   free(wd);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   if (!wd) return;
+   edje_object_size_min_calc(wd->edje, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static Eina_Bool
+_elm_fileselector_entry_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd)
+     return EINA_FALSE;
+
+   Evas_Object *chain[2];
+
+   /* Direction */
+   if (dir == ELM_FOCUS_PREVIOUS)
+     {
+        chain[0] = wd->button;
+        chain[1] = wd->entry;
+     }
+   else if (dir == ELM_FOCUS_NEXT)
+     {
+        chain[0] = wd->entry;
+        chain[1] = wd->button;
+     }
+   else
+     return EINA_FALSE;
+
+   unsigned char i = elm_widget_focus_get(chain[1]);
+
+   if (elm_widget_focus_next_get(chain[i], dir, next))
+     return EINA_TRUE;
+
+   i = !i;
+
+   Evas_Object *to_focus;
+   if (elm_widget_focus_next_get(chain[i], dir, &to_focus))
+     {
+        *next = to_focus;
+        return !!i;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *style = elm_widget_style_get(obj);
+   char buf[1024];
+
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->edje, "fileselector_entry", "base", style);
+   if (elm_object_disabled_get(obj))
+      edje_object_signal_emit(wd->edje, "elm,state,disabled", "elm");
+
+   if (!style) style = "default";
+   snprintf(buf, sizeof(buf), "fileselector_entry/%s", style);
+   elm_widget_style_set(wd->button, buf);
+   elm_widget_style_set(wd->entry, buf);
+
+   edje_object_part_swallow(obj, "elm.swallow.button", wd->button);
+   edje_object_part_swallow(obj, "elm.swallow.entry", wd->entry);
+
+   edje_object_message_signal_process(wd->edje);
+   edje_object_scale_set
+     (wd->edje, 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);
+   Eina_Bool val = elm_widget_disabled_get(obj);
+   if (!wd) return;
+   if (val)
+     edje_object_signal_emit(wd->edje, "elm,state,disabled", "elm");
+   else
+     edje_object_signal_emit(wd->edje, "elm,state,enabled", "elm");
+
+   elm_widget_disabled_set(wd->button, val);
+   elm_widget_disabled_set(wd->entry, val);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+/**
+ * Add a new file selector entry into the parent object.
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI Evas_Object *
+elm_fileselector_entry_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "fileselector_entry");
+   elm_widget_type_set(obj, "fileselector_entry");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_focus_next_hook_set(obj, _elm_fileselector_entry_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+
+   wd->edje = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->edje, "fileselector_entry", "base", "default");
+   elm_widget_resize_object_set(obj, wd->edje);
+
+   wd->button = elm_fileselector_button_add(obj);
+   elm_widget_style_set(wd->button, "fileselector_entry/default");
+   edje_object_part_swallow(wd->edje, "elm.swallow.button", wd->button);
+   elm_widget_sub_object_add(obj, wd->button);
+   evas_object_event_callback_add
+     (wd->button, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+   elm_fileselector_button_expandable_set(wd->button,
+                                          _elm_config->fileselector_expand_enable);
+
+#define SIG_FWD(name)                                                   \
+   evas_object_smart_callback_add(wd->button, SIG_##name, _##name##_fwd, obj)
+   SIG_FWD(CLICKED);
+   SIG_FWD(UNPRESSED);
+   SIG_FWD(FILE_CHOSEN);
+#undef SIG_FWD
+
+   wd->entry = elm_scrolled_entry_add(obj);
+   elm_widget_style_set(wd->entry, "fileselector_entry/default");
+   elm_scrolled_entry_single_line_set(wd->entry, EINA_TRUE);
+   elm_scrolled_entry_editable_set(wd->entry, EINA_TRUE);
+   edje_object_part_swallow(wd->edje, "elm.swallow.entry", wd->entry);
+   elm_widget_sub_object_add(obj, wd->entry);
+   evas_object_event_callback_add
+     (wd->entry, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+
+#define SIG_FWD(name)                                                   \
+   evas_object_smart_callback_add(wd->entry, SIG_##name, _##name##_fwd, obj)
+   SIG_FWD(CHANGED);
+   SIG_FWD(ACTIVATED);
+   SIG_FWD(PRESS);
+   SIG_FWD(LONGPRESSED);
+   SIG_FWD(CLICKED);
+   SIG_FWD(CLICKED_DOUBLE);
+   SIG_FWD(FOCUSED);
+   SIG_FWD(UNFOCUSED);
+   SIG_FWD(SELECTION_PASTE);
+   SIG_FWD(SELECTION_COPY);
+   SIG_FWD(SELECTION_CUT);
+#undef SIG_FWD
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the label used in the file selector entry.
+ *
+ * @param obj The entry object
+ * @param label The text label text to be displayed on the entry
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_button_label_set(Evas_Object *obj, const char *label)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_label_set(wd->button, label);
+}
+
+EAPI const char *
+elm_fileselector_entry_button_label_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_fileselector_button_label_get(wd->button);
+}
+
+/**
+ * Set the path to start the entry's file selector with, when clicked.
+ *
+ * @param obj The entry object
+ * @param path Path to a file/directory
+ *
+ * Default path is "HOME" environment variable's value.
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_selected_set(Evas_Object *obj, const char *path)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_path_set(wd->button, path);
+}
+
+/**
+ * Get the <b>last</b> path which the entry's file selector was set to.
+ *
+ * @param obj The entry object
+ * @param path Path to a file/directory
+ *
+ * Default path is "HOME" environment variable's value.
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI const char *
+elm_fileselector_entry_selected_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_fileselector_button_path_get(wd->button);
+}
+
+/**
+ * Set the title of the file selector entry's window.
+ *
+ * @param obj The entry object
+ * @param title The title string
+ *
+ * Note that it will only take any effect if the fileselector entry
+ * not at "inwin mode".
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_window_title_set(Evas_Object *obj, const char *title)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_window_title_set(wd->button, title);
+}
+
+/**
+ * Get the title of the file selector entry's window.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI const char *
+elm_fileselector_entry_window_title_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_fileselector_button_window_title_get(wd->button);
+}
+
+/**
+ * Set the size of the file selector entry's window.
+ *
+ * @param obj The entry object
+ * @param width The width
+ * @param height The height
+ *
+ * Note that it will only take any effect if the fileselector entry not at
+ * "inwin mode". Default size for the window (when applicable) is 400x400.
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_window_size_set(Evas_Object *obj, Evas_Coord width, Evas_Coord height)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_window_size_set(wd->button, width, height);
+}
+
+/**
+ * Get the size of the file selector entry's window.
+ *
+ * @param obj The entry object
+ * @param width Pointer into which to store the width value
+ * @param height Pointer into which to store the height value
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_window_size_get(const Evas_Object *obj, Evas_Coord *width, Evas_Coord *height)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_window_size_get(wd->button, width, height);
+}
+
+/**
+ * Set the starting path of the file selector entry's window.
+ *
+ * @param obj The entry object
+ * @param path The path string
+ *
+ * It must be a <b>directory</b> path.
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_path_set(Evas_Object *obj, const char *path)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_path_set(wd->button, path);
+   elm_scrolled_entry_entry_set(wd->entry, path);
+}
+
+/**
+ * Get the <b>last</b> path of the file selector entry's window.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI const char *
+elm_fileselector_entry_path_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_scrolled_entry_entry_get(wd->entry);
+}
+
+/**
+ * Set whether the entry's file selector is to present itself as an
+ * Elementary Generic List (which will expand its entries for nested
+ * directories) or as canonical list, which will be rendered again
+ * with the contents of each selected directory.
+ *
+ * @param obj The entry object
+ * @param value The expandable flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_expandable_set(Evas_Object *obj, Eina_Bool value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_expandable_set(wd->button, value);
+}
+
+/**
+ * Get the entry's file selector expandable flag.
+ *
+ * @param obj The entry object
+ * @return value The expandable flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI Eina_Bool
+elm_fileselector_entry_expandable_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 elm_fileselector_button_expandable_get(wd->button);
+}
+
+/**
+ * Set whether the entry's file selector list is to display folders
+ * only or the directory contents, as well.
+ *
+ * @param obj The entry object
+ * @param value The "folder only" flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_folder_only_set(Evas_Object *obj, Eina_Bool value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_folder_only_set(wd->button, value);
+}
+
+/**
+ * Get the entry's file selector "folder only" flag.
+ *
+ * @param obj The entry object
+ * @return value The "folder only" flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI Eina_Bool
+elm_fileselector_entry_folder_only_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 elm_fileselector_button_folder_only_get(wd->button);
+}
+
+/**
+ * Set whether the entry's file selector has an editable text entry
+ * which will hold its current selection.
+ *
+ * @param obj The entry object
+ * @param value The "is save" flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_is_save_set(Evas_Object *obj, Eina_Bool value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_is_save_set(wd->button, value);
+}
+
+/**
+ * Get the entry's file selector "is save" flag.
+ *
+ * @param obj The entry object
+ * @return value The "is save" flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI Eina_Bool
+elm_fileselector_entry_is_save_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 elm_fileselector_button_is_save_get(wd->button);
+}
+
+/**
+ * Set whether the entry's file selector will raise an Elementary
+ * Inner Window, instead of a dedicated Elementary Window. By default,
+ * it won't.
+ *
+ * @param obj The entry object
+ * @param value The "inwin mode" flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_inwin_mode_set(Evas_Object *obj, Eina_Bool value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_inwin_mode_set(wd->button, value);
+}
+
+/**
+ * Get the entry's file selector "inwin mode" flag.
+ *
+ * @param obj The entry object
+ * @return value The "inwin mode" flag
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI Eina_Bool
+elm_fileselector_entry_inwin_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 elm_fileselector_button_inwin_mode_get(wd->button);
+}
+
+/**
+ * Set the icon used for the entry button
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ *
+ * @param obj The entry object
+ * @param icon  The image for the entry
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI void
+elm_fileselector_entry_button_icon_set(Evas_Object *obj, Evas_Object *icon)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_fileselector_button_icon_set(wd->button, icon);
+}
+
+/**
+ * Get the icon used for the entry button
+ *
+ * @param obj The entry object
+ * @return The image for the entry
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI Evas_Object *
+elm_fileselector_entry_button_icon_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_fileselector_button_icon_get(wd->button);
+}
+
+/**
+ * Unset the icon used for the entry button
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The entry object
+ * @return The icon object that was being used
+ *
+ * @ingroup File_Selector_Entry
+ */
+EAPI Evas_Object *
+elm_fileselector_entry_button_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_fileselector_button_icon_unset(wd->button);
+}
diff --git a/src/lib/elc_hoversel.c b/src/lib/elc_hoversel.c
new file mode 100644 (file)
index 0000000..0ee816e
--- /dev/null
@@ -0,0 +1,721 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Hoversel
+ *
+ * A hoversel is a button that pops up a list of items (automatically
+ * choosing the direction to display) that have a lable and/or an icon to
+ * select from. It is a convenience widget to avoid the need to do all the
+ * piecing together yourself. It is intended for a small number of items in
+ * the hoversel menu (no more than 8), though is capable of many more.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * clicked  - the user clicked the hoversel button and popped up the sel
+ *
+ * selected - an item in the hoversel list is selected. event_info is the item
+ * selected - Elm_Hoversel_Item
+ *
+ * dismissed - the hover is dismissed
+ */
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *btn, *hover;
+   Evas_Object *hover_parent;
+   Eina_List *items;
+   Eina_Bool horizontal : 1;
+   Eina_Bool expanded   : 1;
+};
+
+struct _Elm_Hoversel_Item
+{
+   Elm_Widget_Item base;
+   const char *label;
+   const char *icon_file;
+   const char *icon_group;
+   Elm_Icon_Type icon_type;
+   Evas_Smart_Cb func;
+};
+
+static const char *widtype = NULL;
+static void _del_pre_hook(Evas_Object *obj);
+static void _del_hook(Evas_Object *obj);
+static void _activate(Evas_Object *obj);
+static void _activate_hook(Evas_Object *obj);
+static void _disable_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 _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Elm_Hoversel_Item *item;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_hoversel_hover_end(obj);
+   elm_hoversel_hover_parent_set(obj, NULL);
+   EINA_LIST_FREE(wd->items, item)
+     {
+        elm_widget_item_pre_notify_del(item);
+       eina_stringshare_del(item->label);
+       eina_stringshare_del(item->icon_file);
+       eina_stringshare_del(item->icon_group);
+        elm_widget_item_del(item);
+     }
+}
+
+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);
+   char buf[4096];
+   if (!wd) return;
+   elm_hoversel_hover_end(obj);
+   if (wd->horizontal)
+      snprintf(buf, sizeof(buf), "hoversel_horizontal/%s", elm_widget_style_get(obj));
+   else
+      snprintf(buf, sizeof(buf), "hoversel_vertical/%s", elm_widget_style_get(obj));
+   elm_object_style_set(wd->btn, buf);
+   elm_object_disabled_set(wd->btn, elm_widget_disabled_get(obj));
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_object_disabled_set(wd->btn, elm_widget_disabled_get(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_min_get(wd->btn, &minw, &minh);
+   evas_object_size_hint_max_get(wd->btn, &maxw, &maxh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+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->btn);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_hover_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_hoversel_hover_end(data);
+}
+
+static void
+_item_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Hoversel_Item *item = data;
+   Evas_Object *obj2 = item->base.widget;
+
+   elm_hoversel_hover_end(obj2);
+   if (item->func) item->func((void *)item->base.data, obj2, item);
+   evas_object_smart_callback_call(obj2, "selected", item);
+}
+
+static void
+_activate(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *bt, *bx, *ic;
+   const Eina_List *l;
+   const Elm_Hoversel_Item *item;
+   char buf[4096];
+
+   if (!wd) return;
+   if (wd->expanded)
+     {
+        elm_hoversel_hover_end(obj);
+        return;
+     }
+   wd->expanded = EINA_TRUE;
+
+   if (elm_widget_disabled_get(obj)) return;
+   wd->hover = elm_hover_add(obj);
+   if (wd->horizontal)
+     snprintf(buf, sizeof(buf), "hoversel_horizontal/%s", elm_widget_style_get(obj));
+   else
+     snprintf(buf, sizeof(buf), "hoversel_vertical/%s", elm_widget_style_get(obj));
+   elm_object_style_set(wd->hover, buf);
+   evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked, obj);
+   elm_hover_parent_set(wd->hover, wd->hover_parent);
+   elm_hover_target_set(wd->hover, wd->btn);
+
+   bx = elm_box_add(wd->hover);
+   elm_box_homogenous_set(bx, 1);
+   
+   elm_box_horizontal_set(bx, wd->horizontal);
+   
+   if (wd->horizontal)
+     snprintf(buf, sizeof(buf), "hoversel_horizontal_entry/%s",
+              elm_widget_style_get(obj));
+   else
+     snprintf(buf, sizeof(buf), "hoversel_vertical_entry/%s",
+              elm_widget_style_get(obj));
+   EINA_LIST_FOREACH(wd->items, l, item)
+     {
+       bt = elm_button_add(wd->hover);
+       elm_object_style_set(bt, buf);
+       elm_button_label_set(bt, item->label);
+       if (item->icon_file)
+         {
+            ic = elm_icon_add(obj);
+            elm_icon_scale_set(ic, 0, 1);
+            if (item->icon_type == ELM_ICON_FILE)
+              elm_icon_file_set(ic, item->icon_file, item->icon_group);
+            else if (item->icon_type == ELM_ICON_STANDARD)
+              elm_icon_standard_set(ic, item->icon_file);
+            elm_button_icon_set(bt, ic);
+            evas_object_show(ic);
+         }
+       evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+       evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       elm_box_pack_end(bx, bt);
+       evas_object_smart_callback_add(bt, "clicked", _item_clicked, item);
+       evas_object_show(bt);
+     }
+
+   if (wd->horizontal)
+     elm_hover_content_set(wd->hover,
+                           elm_hover_best_content_location_get(wd->hover,
+                                                               ELM_HOVER_AXIS_HORIZONTAL),
+                           bx);
+   else
+     elm_hover_content_set(wd->hover,
+                           elm_hover_best_content_location_get(wd->hover,
+                                                               ELM_HOVER_AXIS_VERTICAL),
+                           bx);
+   evas_object_show(bx);
+
+   evas_object_show(wd->hover);
+   evas_object_smart_callback_call(obj, "clicked", NULL);
+
+//   if (wd->horizontal) evas_object_hide(wd->btn);
+}
+
+static void
+_activate_hook(Evas_Object *obj)
+{
+   _activate(obj);
+}
+
+static void
+_button_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _activate(data);
+}
+
+static void
+_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->hover_parent = NULL;
+}
+
+/**
+ * Add a new Hoversel object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Hoversel
+ */
+EAPI Evas_Object *
+elm_hoversel_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "hoversel");
+   elm_widget_type_set(obj, "hoversel");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   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);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_activate_hook_set(obj, _activate_hook);
+   elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+
+   wd->btn = elm_button_add(parent);
+   wd->expanded = EINA_FALSE;
+   elm_widget_resize_object_set(obj, wd->btn);
+   evas_object_event_callback_add(wd->btn, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                 _changed_size_hints, obj);
+   evas_object_smart_callback_add(wd->btn, "clicked", _button_clicked, obj);
+   elm_widget_sub_object_add(obj, wd->btn);
+
+   elm_hoversel_hover_parent_set(obj, parent);
+   _theme_hook(obj);
+   return obj;
+}
+
+/**
+ * Set the Hover parent
+ *
+ * Sets the hover parent object. Should probably be the window that the hoversel
+ * is in.  See Hover objects for more information.
+ *
+ * @param obj The hoversel object
+ * @param parent The parent to use
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->hover_parent)
+     evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL,
+                                    _parent_del, obj);
+   wd->hover_parent = parent;
+   if (wd->hover_parent)
+     evas_object_event_callback_add(wd->hover_parent, EVAS_CALLBACK_DEL,
+                                    _parent_del, obj);
+}
+
+/**
+ * Get the Hover parent
+ *
+ * Gets the hover parent object. Should probably be the window that the hoversel
+ * is in.  See Hover objects for more information.
+ *
+ * @param obj The hoversel object
+ * @return The used parent
+ *
+ * @ingroup Hoversel
+ */
+EAPI Evas_Object *
+elm_hoversel_hover_parent_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->hover_parent;
+}
+
+/**
+ * Set the hoversel button label
+ *
+ * This sets the label of the button that is always visible (before it is
+ * clicked and expanded). Also see elm_button_label_set().
+ *
+ * @param obj The hoversel object
+ * @param label The label text.
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_label_set(Evas_Object *obj, const char *label)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_button_label_set(wd->btn, label);
+}
+
+/**
+ * Get the hoversel button label
+ *
+ * @param obj The hoversel object
+ * @return The label text.
+ *
+ * @ingroup Hoversel
+ */
+EAPI const char *
+elm_hoversel_label_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->btn)) return NULL;
+   return elm_button_label_get(wd->btn);
+}
+
+/**
+ * This sets the hoversel to expand horizontally.  The initial button
+ * will display horizontally regardless of this setting.
+ *
+ * @param obj The hoversel object
+ * @param horizontal If true, the hover will expand horizontally to the right.
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->horizontal = !!horizontal;
+}
+
+
+/**
+ * This returns whether the hoversel is set to expand horizontally.
+ *
+ * @param obj The hoversel object
+ * @return If true, the hover will expand horizontally to the right.
+ *
+ * @ingroup Hoversel
+ */
+EAPI Eina_Bool
+elm_hoversel_horizontal_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->horizontal;
+}
+
+/**
+ * Set the icon of the hoversel button
+ *
+ * Sets the icon of the button that is always visible (before it is clicked
+ * and expanded). Also see elm_button_icon_set().
+ * Once the icon object is set, a previously set one will be deleted
+ * If you want to keep that old content object, use the
+ * elm_hoversel_icon_unset() function.
+ *
+ * @param obj The hoversel object
+ * @param icon The icon object
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_icon_set(Evas_Object *obj, Evas_Object *icon)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_button_icon_set(wd->btn, icon);
+}
+
+/**
+ * Get the icon of the hoversel button
+ *
+ * Get the icon of the button that is always visible (before it is clicked
+ * and expanded). Also see elm_button_icon_get().
+ *
+ * @param obj The hoversel object
+ * @return The icon object
+ *
+ * @ingroup Hoversel
+ */
+EAPI Evas_Object *
+elm_hoversel_icon_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->btn)) return NULL;
+   return elm_button_icon_get(wd->btn);
+}
+
+/**
+ * Get the icon of the hoversel button
+ *
+ * Unparent and return the icon of the button that is always visible
+ * (before it is clicked and expanded). Also see elm_button_icon_unset().
+ *
+ * @param obj The hoversel object
+ * @return The icon object that was being used
+ *
+ * @ingroup Hoversel
+ */
+EAPI Evas_Object *
+elm_hoversel_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->btn)) return NULL;
+   return elm_button_icon_unset(wd->btn);
+}
+
+/**
+ * This triggers the hoversel popup from code, the same as though the
+ * user clicked the button.
+ *
+ * @param obj The hoversel object
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_hover_begin(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->hover) return;
+   _activate(obj);
+}
+
+/**
+ * This ends the hoversel popup as though the user clicked outside the hover.
+ *
+ * @param obj The hoversel object
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_hover_end(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (!wd->hover) return;
+   wd->expanded = EINA_FALSE;
+   evas_object_del(wd->hover);
+   wd->hover = NULL;
+   evas_object_smart_callback_call(obj, "dismissed", NULL);
+}
+
+/**
+ * Returns whether the hoversel is expanded.
+ *
+ * @param obj The hoversel object
+ * @return  This will return EINA_TRUE if the hoversel
+ * is expanded or EINA_FALSE if it is not expanded.
+ *
+ * @ingroup Hoversel
+ */
+EAPI Eina_Bool
+elm_hoversel_expanded_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->hover) ? EINA_TRUE : EINA_FALSE;
+}
+  
+/**
+ * This will remove all the children items from the hoversel. (should not be
+ * called while the hoversel is active; use elm_hoversel_expanded_get()
+ * to check first).
+ *
+ * @param obj The hoversel object
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_clear(Evas_Object *obj)
+{
+   Elm_Hoversel_Item *item;
+   Eina_List *l, *ll;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_LIST_FOREACH_SAFE(wd->items, l, ll, item) elm_hoversel_item_del(item);
+}
+
+/**
+ * Get the list of items within the given hoversel.
+ *
+ * @param obj The hoversel object
+ * @return Returns a list of Elm_Hoversel_Item*
+ *
+ * @ingroup Hoversel
+ */
+EAPI const Eina_List *
+elm_hoversel_items_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->items;
+}
+
+/**
+ * Add an item to the hoversel button
+ *
+ * This adds an item to the hoversel to show when it is clicked. Note: if you
+ * need to use an icon from an edje file then use elm_hoversel_item_icon_set()
+ * right after the this function, and set icon_file to NULL here.
+ *
+ * @param obj The hoversel object
+ * @param label The text label to use for the item (NULL if not desired)
+ * @param icon_file An image file path on disk to use for the icon or standard
+ * icon name (NULL if not desired)
+ * @param icon_type The icon type if relevant
+ * @param func Convenience function to call when this item is selected
+ * @param data Data to pass to item-related functions
+ * @return A handle to the item added.
+ *
+ * @ingroup Hoversel
+ */
+EAPI Elm_Hoversel_Item *
+elm_hoversel_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, 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;
+   Elm_Hoversel_Item *item = elm_widget_item_new(obj, Elm_Hoversel_Item);
+   if (!item) return NULL;
+   wd->items = eina_list_append(wd->items, item);
+   item->label = eina_stringshare_add(label);
+   item->icon_file = eina_stringshare_add(icon_file);
+   item->icon_type = icon_type;
+   item->func = func;
+   item->base.data = data;
+   return item;
+}
+
+/**
+ * Delete an item from the hoversel
+ *
+ * This deletes the item from the hoversel (should not be called while the
+ * hoversel is active; use elm_hoversel_expanded_get()
+ * to check first).
+ *
+ * @param item The item to delete
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_item_del(Elm_Hoversel_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   Widget_Data *wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+   elm_hoversel_hover_end(item->base.widget);
+   wd->items = eina_list_remove(wd->items, item);
+   elm_widget_item_pre_notify_del(item);
+   eina_stringshare_del(item->label);
+   eina_stringshare_del(item->icon_file);
+   eina_stringshare_del(item->icon_group);
+   elm_widget_item_del(item);
+}
+
+/**
+ * Set the function called when an item within the hoversel
+ * is freed. That function will receive these parameters:
+ *
+ * void *item_data
+ * Evas_Object *the_item_object
+ * Elm_Hoversel_Item *the_object_struct
+ *
+ * @param item The item to set the callback on
+ * @param func The function called
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_item_del_cb_set(Elm_Hoversel_Item *item, Evas_Smart_Cb func)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_del_cb_set(item, func);
+}
+
+/**
+ * This returns the data pointer supplied with elm_hoversel_item_add() that
+ * will be passed to associated function callbacks.
+ *
+ * @param item The item to get the data from
+ * @return The data pointer set with elm_hoversel_item_add()
+ *
+ * @ingroup Hoversel
+ */
+EAPI void *
+elm_hoversel_item_data_get(const Elm_Hoversel_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_data_get(item);
+}
+
+/**
+ * This returns the label text of the given hoversel item.
+ *
+ * @param item The item to get the label
+ * @return The label text of the hoversel item
+ *
+ * @ingroup Hoversel
+ */
+EAPI const char *
+elm_hoversel_item_label_get(const Elm_Hoversel_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->label;
+}
+
+/**
+ * This sets the icon for the given hoversel item. The icon can be loaded from
+ * the standard set, from an image file, or from an edje file.
+ *
+ * @param item The item to set the icon
+ * @param icon_file An image file path on disk to use for the icon or standard
+ * icon name
+ * @param icon_group The edje group to use if @p icon_file is an edje file. Set this
+ * to NULL if the icon is not an edje file
+ * @param icon_type The icon type
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_item_icon_set(Elm_Hoversel_Item *item, const char *icon_file, const char *icon_group, Elm_Icon_Type icon_type)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   eina_stringshare_replace(&item->icon_file, icon_file);
+   eina_stringshare_replace(&item->icon_group, icon_group);
+   item->icon_type = icon_type;
+}
+
+/**
+ * Get the icon object of the hoversel item
+ *
+ * @param item The item to get the icon from
+ * @param icon_file The image file path on disk used for the icon or standard
+ * icon name
+ * @param icon_group The edje group used if @p icon_file is an edje file. NULL
+ * if the icon is not an edje file
+ * @param icon_type The icon type
+ *
+ * @ingroup Hoversel
+ */
+EAPI void
+elm_hoversel_item_icon_get(const Elm_Hoversel_Item *item, const char **icon_file, const char **icon_group, Elm_Icon_Type *icon_type)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (icon_file) *icon_file = item->icon_file;
+   if (icon_group) *icon_group = item->icon_group;
+   if (icon_type) *icon_type = item->icon_type;
+}
+
diff --git a/src/lib/elc_scrolled_entry.c b/src/lib/elc_scrolled_entry.c
new file mode 100644 (file)
index 0000000..f7d4433
--- /dev/null
@@ -0,0 +1,1611 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Scrolled_Entry Scrolled_Entry
+ *
+ * A scrolled entry is a convenience widget which shows
+ * a box that the user can enter text into.  Unlike an
+ * @ref Entry widget, scrolled entries scroll with user
+ * input so that the window will not expand if the length
+ * of text inside the entry exceeds the initial size of the
+ * widget.
+ *
+ * Signals that you can add callbacks for are:
+ * - "changed" - The text within the entry was changed
+ * - "activated" - The entry has received focus and the cursor
+ * - "press" - The entry has been clicked
+ * - "longpressed" - The entry has been clicked for a couple seconds
+ * - "clicked" - The entry has been clicked
+ * - "clicked,double" - The entry has been double clicked
+ * - "focused" - The entry has received focus
+ * - "unfocused" - The entry has lost focus
+ * - "selection,paste" - A paste action has occurred
+ * - "selection,copy" - A copy action has occurred
+ * - "selection,cut" - A cut action has occurred
+ * - "selection,start" - A selection has begun
+ * - "selection,changed" - The selection has changed
+ * - "selection,cleared" - The selection has been cleared
+ * - "cursor,changed" - The cursor has changed
+ * - "anchor,clicked" - The anchor has been clicked
+ */
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
+typedef struct _Elm_Entry_Item_Provider Elm_Entry_Item_Provider;
+typedef struct _Elm_Entry_Text_Filter Elm_Entry_Text_Filter;
+
+struct _Widget_Data
+{
+   Evas_Object *scroller;
+   Evas_Object *entry;
+   Evas_Object *icon;
+   Evas_Object *end;
+   Elm_Scroller_Policy policy_h, policy_v;
+   Eina_List *items;
+   Eina_List *item_providers;
+   Eina_List *text_filters;
+   Eina_Bool single_line : 1;
+};
+
+struct _Elm_Entry_Context_Menu_Item
+{
+   Evas_Object *obj;
+   Evas_Smart_Cb func;
+   void *data;
+};
+
+struct _Elm_Entry_Item_Provider
+{
+   Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item);
+   void *data;
+};
+
+struct _Elm_Entry_Text_Filter
+{
+   void (*func) (void *data, Evas_Object *entry, char **text);
+   void *data;
+};
+
+static const char *widtype = NULL;
+
+static const char SIG_CHANGED[] = "changed";
+static const char SIG_ACTIVATED[] = "activated";
+static const char SIG_PRESS[] = "press";
+static const char SIG_LONGPRESSED[] = "longpressed";
+static const char SIG_CLICKED[] = "clicked";
+static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
+static const char SIG_FOCUSED[] = "focused";
+static const char SIG_UNFOCUSED[] = "unfocused";
+static const char SIG_SELECTION_PASTE[] = "selection,paste";
+static const char SIG_SELECTION_COPY[] = "selection,copy";
+static const char SIG_SELECTION_CUT[] = "selection,cut";
+static const char SIG_SELECTION_START[] = "selection,start";
+static const char SIG_SELECTION_CHANGED[] = "selection,changed";
+static const char SIG_SELECTION_CLEARED[] = "selection,cleared";
+static const char SIG_CURSOR_CHANGED[] = "cursor,changed";
+static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CHANGED, ""},
+  {SIG_ACTIVATED, ""},
+  {SIG_PRESS, ""},
+  {SIG_LONGPRESSED, ""},
+  {SIG_CLICKED, ""},
+  {SIG_CLICKED_DOUBLE, ""},
+  {SIG_FOCUSED, ""},
+  {SIG_UNFOCUSED, ""},
+  {SIG_SELECTION_PASTE, ""},
+  {SIG_SELECTION_COPY, ""},
+  {SIG_SELECTION_CUT, ""},
+  {SIG_SELECTION_START, ""},
+  {SIG_SELECTION_CHANGED, ""},
+  {SIG_SELECTION_CLEARED, ""},
+  {SIG_CURSOR_CHANGED, ""},
+  {SIG_ANCHOR_CLICKED, ""},
+  {NULL, NULL}
+};
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Elm_Entry_Context_Menu_Item *ci;
+   Elm_Entry_Item_Provider *ip;
+   Elm_Entry_Text_Filter *tf;
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   EINA_LIST_FREE(wd->items, ci)
+      free(ci);
+   EINA_LIST_FREE(wd->item_providers, ip)
+      free(ip);
+   EINA_LIST_FREE(wd->text_filters, tf)
+      free(tf);
+
+   if (!wd) return;
+   free(wd);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   Evas_Coord minw, minh, minw_scr, minh_scr;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   evas_object_size_hint_min_get(obj, &minw, &minh);
+   evas_object_size_hint_min_get(wd->scroller, &minw_scr, &minh_scr);
+   if (minw < minw_scr) minw = minw_scr;
+   if (minh < minh_scr) minh = minh_scr;
+
+   evas_object_size_hint_min_set(obj, minw, minh);
+   if (wd->single_line)
+     evas_object_size_hint_max_set(obj, -1, minh);
+   else
+     evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_object_style_set(wd->entry, elm_widget_style_get(obj));
+   elm_object_style_set(wd->scroller, elm_widget_style_get(obj));
+   elm_object_disabled_set(wd->entry, elm_widget_disabled_get(obj));
+   elm_object_disabled_set(wd->scroller, elm_widget_disabled_get(obj));
+   _sizing_eval(obj);
+}
+
+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 void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_object_disabled_set(wd->entry, elm_widget_disabled_get(obj));
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_object_signal_emit(wd->entry, emission, source);
+   elm_object_signal_emit(wd->scroller, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_object_signal_callback_add(wd->entry, emission, source, func_cb, data);
+   elm_object_signal_callback_add(wd->scroller, emission, source, func_cb,
+        data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   elm_object_signal_callback_del(wd->entry, emission, source, func_cb);
+   elm_object_signal_callback_del(wd->scroller, emission, source, func_cb);
+}
+
+static void
+_on_focus_region_hook(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   elm_widget_focus_region_get(wd->entry, x, y, w, h);
+}
+
+static void
+_changed_size_hints(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   _sizing_eval(obj);
+}
+
+static void
+_entry_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   _sizing_eval(data);
+   evas_object_smart_callback_call(data, SIG_CHANGED, event_info);
+}
+
+static void
+_entry_activated(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_ACTIVATED, event_info);
+}
+
+static void
+_entry_press(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_PRESS, event_info);
+}
+
+static void
+_entry_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_CLICKED, event_info);
+}
+
+static void
+_entry_clicked_double(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, event_info);
+}
+
+static void
+_entry_cursor_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_CURSOR_CHANGED, event_info);
+}
+
+static void
+_entry_anchor_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, event_info);
+}
+
+static void
+_entry_selection_start(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_SELECTION_START, event_info);
+}
+
+static void
+_entry_selection_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_SELECTION_CHANGED, event_info);
+}
+
+static void
+_entry_selection_cleared(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_SELECTION_CLEARED, event_info);
+}
+
+static void
+_entry_selection_paste(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, event_info);
+}
+
+static void
+_entry_selection_copy(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_SELECTION_COPY, event_info);
+}
+
+static void
+_entry_selection_cut(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_SELECTION_CUT, event_info);
+}
+
+static void
+_entry_longpressed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_LONGPRESSED, event_info);
+}
+
+static void
+_entry_focused(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_FOCUSED, event_info);
+}
+
+static void
+_entry_unfocused(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   evas_object_smart_callback_call(data, SIG_UNFOCUSED, event_info);
+}
+
+static void
+_context_item_wrap_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Entry_Context_Menu_Item *ci = data;
+   ci->func(ci->data, ci->obj, event_info);
+}
+
+static Evas_Object *
+_item_provider_wrap_cb(void *data, Evas_Object *obj __UNUSED__, const char *item)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Eina_List *l;
+   Elm_Entry_Item_Provider *ip;
+
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        Evas_Object *o;
+        o = ip->func(ip->data, data, item);
+        if (o) return o;
+     }
+   return NULL;
+}
+
+static void
+_text_filter_wrap_cb(void *data, Evas_Object *obj __UNUSED__, char **text)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Eina_List *l;
+   Elm_Entry_Text_Filter *tf;
+
+   EINA_LIST_FOREACH(wd->text_filters, l, tf)
+     {
+        tf->func(tf->data, data, text);
+        if (!*text) break;
+     }
+}
+
+/**
+ * This adds a scrolled entry to @p parent object.
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Evas_Object *
+elm_scrolled_entry_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "scrolled_entry");
+   elm_widget_type_set(obj, "scrolled_entry");
+   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_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_on_focus_region_hook_set(obj, _on_focus_region_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+
+   wd->scroller = elm_scroller_add(obj);
+   elm_scroller_custom_widget_base_theme_set(wd->scroller, "scroller", "entry");
+   elm_widget_resize_object_set(obj, wd->scroller);
+   evas_object_size_hint_weight_set(wd->scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(wd->scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scroller_bounce_set(wd->scroller, EINA_FALSE, EINA_FALSE);
+   elm_scroller_propagate_events_set(wd->scroller, EINA_TRUE);
+   evas_object_show(wd->scroller);
+
+   wd->entry = elm_entry_add(obj);
+   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->scroller, wd->entry);
+   evas_object_show(wd->entry);
+
+   elm_entry_text_filter_prepend(wd->entry, _text_filter_wrap_cb, obj);
+   elm_entry_item_provider_prepend(wd->entry, _item_provider_wrap_cb, obj);
+
+   evas_object_smart_callback_add(wd->entry, "changed", _entry_changed, obj);
+   evas_object_smart_callback_add(wd->entry, "activated", _entry_activated, obj);
+   evas_object_smart_callback_add(wd->entry, "press", _entry_press, obj);
+   evas_object_smart_callback_add(wd->entry, "clicked", _entry_clicked, obj);
+   evas_object_smart_callback_add(wd->entry, "clicked,double", _entry_clicked_double, obj);
+   evas_object_smart_callback_add(wd->entry, "cursor,changed", _entry_cursor_changed, obj);
+   evas_object_smart_callback_add(wd->entry, "anchor,clicked", _entry_anchor_clicked, obj);
+   evas_object_smart_callback_add(wd->entry, "selection,start", _entry_selection_start, obj);
+   evas_object_smart_callback_add(wd->entry, "selection,changed", _entry_selection_changed, obj);
+   evas_object_smart_callback_add(wd->entry, "selection,cleared", _entry_selection_cleared, obj);
+   evas_object_smart_callback_add(wd->entry, "selection,paste", _entry_selection_paste, obj);
+   evas_object_smart_callback_add(wd->entry, "selection,copy", _entry_selection_copy, obj);
+   evas_object_smart_callback_add(wd->entry, "selection,cut", _entry_selection_cut, obj);
+   evas_object_smart_callback_add(wd->entry, "longpressed", _entry_longpressed, obj);
+   evas_object_smart_callback_add(wd->entry, "focused", _entry_focused, obj);
+   evas_object_smart_callback_add(wd->entry, "unfocused", _entry_unfocused, obj);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                  _changed_size_hints, NULL);
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * This sets a widget to be displayed to the left of a scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ * @param icon The widget to display on the left side of the scrolled
+ * entry.
+ *
+ * @note A previously set widget will be destroyed.
+ * @note If the object being set does not have minimum size hints set,
+ * it won't get properly displayed.
+ *
+ * @ingroup Scrolled_Entry
+ * @see elm_scrolled_entry_end_set
+ */
+EAPI void
+elm_scrolled_entry_icon_set(Evas_Object *obj, Evas_Object *icon)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *edje;
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(icon);
+   if (wd->icon == icon) return;
+   if (wd->icon) evas_object_del(wd->icon);
+   wd->icon = icon;
+   edje = _elm_scroller_edje_object_get(wd->scroller);
+   if (!edje) return;
+   edje_object_part_swallow(edje, "elm.swallow.icon", wd->icon);
+   edje_object_signal_emit(edje, "elm,action,show,icon", "elm");
+   _sizing_eval(obj);
+}
+
+/**
+ * Gets the leftmost widget of the scrolled entry. This object is
+ * owned by the scrolled entry and should not be modified.
+ *
+ * @param obj The scrolled entry object
+ * @return the left widget inside the scroller
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Evas_Object *
+elm_scrolled_entry_icon_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->icon;
+}
+
+/**
+ * Unset the leftmost widget of the scrolled entry, unparenting and
+ * returning it.
+ *
+ * @param obj The scrolled entry object
+ * @return the previously set icon sub-object of this entry, on
+ * success.
+ *
+ * @see elm_scrolled_entry_icon_set()
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Evas_Object *
+elm_scrolled_entry_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *ret = NULL;
+   if (!wd) return NULL;
+   if (wd->icon)
+     {
+       Evas_Object *edje = _elm_scroller_edje_object_get(wd->scroller);
+       if (!edje) return NULL;
+       ret = wd->icon;
+       edje_object_part_unswallow(edje, wd->icon);
+       edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
+       wd->icon = NULL;
+       _sizing_eval(obj);
+     }
+   return ret;
+}
+
+/**
+ * Sets the visibility of the left-side widget of the scrolled entry,
+ * set by @elm_scrolled_entry_icon_set().
+ *
+ * @param obj The scrolled entry object
+ * @param setting EINA_TRUE if the object should be displayed,
+ * EINA_FALSE if not.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->icon)) return;
+   if (setting)
+     evas_object_hide(wd->icon);
+   else
+     evas_object_show(wd->icon);
+   _sizing_eval(obj);
+}
+
+/**
+ * This sets a widget to be displayed to the end of a scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ * @param end The widget to display on the right side of the scrolled
+ * entry.
+ *
+ * @note A previously set widget will be destroyed.
+ * @note If the object being set does not have minimum size hints set,
+ * it won't get properly displayed.
+ *
+ * @ingroup Scrolled_Entry
+ * @see elm_scrolled_entry_icon_set
+ */
+EAPI void
+elm_scrolled_entry_end_set(Evas_Object *obj, Evas_Object *end)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *edje;
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(end);
+   if (wd->end == end) return;
+   if (wd->end) evas_object_del(wd->end);
+   wd->end = end;
+   edje = _elm_scroller_edje_object_get(wd->scroller);
+   if (!edje) return;
+   edje_object_part_swallow(edje, "elm.swallow.end", wd->end);
+   edje_object_signal_emit(edje, "elm,action,show,end", "elm");
+   _sizing_eval(obj);
+}
+
+/**
+ * Gets the endmost widget of the scrolled entry. This object is owned
+ * by the scrolled entry and should not be modified.
+ *
+ * @param obj The scrolled entry object
+ * @return the right widget inside the scroller
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Evas_Object *
+elm_scrolled_entry_end_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->end;
+}
+
+/**
+ * Unset the endmost widget of the scrolled entry, unparenting and
+ * returning it.
+ *
+ * @param obj The scrolled entry object
+ * @return the previously set icon sub-object of this entry, on
+ * success.
+ *
+ * @see elm_scrolled_entry_icon_set()
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Evas_Object *
+elm_scrolled_entry_end_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *ret = NULL;
+   if (!wd) return NULL;
+   if (wd->end)
+     {
+       Evas_Object *edje = _elm_scroller_edje_object_get(wd->scroller);
+       if (!edje) return NULL;
+       ret = wd->end;
+       edje_object_part_unswallow(edje, wd->end);
+       edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
+       wd->end = NULL;
+       _sizing_eval(obj);
+     }
+   return ret;
+}
+
+/**
+ * Sets the visibility of the end widget of the scrolled entry, set by
+ * @elm_scrolled_entry_end_set().
+ *
+ * @param obj The scrolled entry object
+ * @param setting EINA_TRUE if the object should be displayed,
+ * EINA_FALSE if not.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->end)) return;
+   if (setting)
+     evas_object_hide(wd->end);
+   else
+     evas_object_show(wd->end);
+   _sizing_eval(obj);
+}
+
+/**
+ * This sets the scrolled entry object not to line wrap.  All input will
+ * be on a single line, and the entry box will scroll with user input.
+ *
+ * @param obj The scrolled entry object
+ * @param single_line If true, the text in the scrolled entry
+ * will be on a single line.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->single_line == single_line) return;
+   elm_entry_single_line_set(wd->entry, single_line);
+   wd->single_line = single_line;
+   if (single_line)
+     {
+       elm_scroller_policy_set(wd->scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+       elm_scroller_content_min_limit(wd->scroller, 0, 1);
+     }
+   else
+     {
+       elm_scroller_policy_set(wd->scroller, wd->policy_h, wd->policy_v);
+       elm_scroller_content_min_limit(wd->scroller, 0, 0);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * This returns true if the scrolled entry has been set to single line mode.
+ * See also elm_scrolled_entry_single_line_set().
+ *
+ * @param obj The scrolled entry object
+ * @return single_line If true, the text in the scrolled entry is set to display
+ * on a single line.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_single_line_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 elm_entry_single_line_get(wd->entry);
+}
+
+
+/**
+ * This sets the scrolled entry object to password mode.  All text entered
+ * and/or displayed within the widget will be replaced with asterisks (*).
+ *
+ * @param obj The scrolled entry object
+ * @param password If true, password mode is enabled.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_password_set(Evas_Object *obj, Eina_Bool password)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_password_set(wd->entry, password);
+}
+
+/**
+ * This returns whether password mode is enabled.
+ * See also elm_scrolled_entry_password_set().
+ *
+ * @param obj The scrolled entry object
+ * @return If true, the scrolled entry is set to display all characters
+ * as asterisks (*).
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_password_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 elm_entry_password_get(wd->entry);
+}
+
+
+/**
+ * This sets the text displayed within the scrolled entry to @p entry.
+ *
+ * @param obj The scrolled entry object
+ * @param entry The text to be displayed
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_entry_set(Evas_Object *obj, const char *entry)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_entry_set(wd->entry, entry);
+}
+
+/**
+ * This returns the text currently shown in object @p entry.
+ * See also elm_scrolled_entry_entry_set().
+ *
+ * @param obj The scrolled entry object
+ * @return The currently displayed text or NULL on failure
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI const char *
+elm_scrolled_entry_entry_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_entry_entry_get(wd->entry);
+}
+
+/**
+ * This returns EINA_TRUE if the entry is empty/there was an error
+ * and EINA_FALSE if it is not empty.
+ *
+ * @param obj The entry object
+ * @return If the entry is empty or not.
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_is_empty(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_TRUE;
+   return elm_entry_is_empty(wd->entry);
+}
+
+/**
+ * This returns all selected text within the scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ * @return The selected text within the scrolled entry or NULL on failure
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI const char *
+elm_scrolled_entry_selection_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_entry_selection_get(wd->entry);
+}
+
+/**
+ * This inserts text in @p entry at the beginning of the scrolled entry
+ * object.
+ *
+ * @param obj The scrolled entry object
+ * @param entry The text to insert
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_entry_insert(Evas_Object *obj, const char *entry)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_entry_insert(wd->entry, entry);
+}
+
+/**
+ * This enables word line wrapping in the scrolled entry object.  It is the opposite
+ * of elm_scrolled_entry_single_line_set().  Additionally, setting this disables
+ * character line wrapping.
+ * See also elm_scrolled_entry_line_char_wrap_set().
+ *
+ * @param obj The scrolled entry object
+ * @param wrap If true, the scrolled entry will be wrapped once it reaches the end
+ * of the object. Wrapping will occur at the end of the word before the end of the
+ * object.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_line_wrap_set(Evas_Object *obj, Eina_Bool wrap)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_line_wrap_set(wd->entry, wrap);
+}
+
+/**
+ * This enables character line wrapping in the scrolled entry object.  It is the opposite
+ * of elm_scrolled_entry_single_line_set().  Additionally, setting this disables
+ * word line wrapping.
+ * See also elm_scrolled_entry_line_wrap_set().
+ *
+ * @param obj The scrolled entry object
+ * @param wrap If true, the scrolled entry will be wrapped once it reaches the end
+ * of the object. Wrapping will occur immediately upon reaching the end of the object.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_line_char_wrap_set(Evas_Object *obj, Eina_Bool wrap)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_line_char_wrap_set(wd->entry, wrap);
+}
+
+/**
+ * This sets the editable attribute of the scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ * @param editable If true, the scrolled entry will be editable by the user.
+ * If false, it will be set to the disabled state.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_editable_set(Evas_Object *obj, Eina_Bool editable)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_editable_set(wd->entry, editable);
+}
+
+/**
+ * This gets the editable attribute of the scrolled entry.
+ * See also elm_scrolled_entry_editable_set().
+ *
+ * @param obj The scrolled entry object
+ * @return If true, the scrolled entry is editable by the user.
+ * If false, it is not editable by the user
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_editable_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 elm_entry_editable_get(wd->entry);
+}
+
+
+/**
+ * This drops any existing text selection within the scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_select_none(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_select_none(wd->entry);
+}
+
+/**
+ * This selects all text within the scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_select_all(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_select_all(wd->entry);
+}
+
+/**
+ * This moves the cursor one place to the right within the entry.
+ *
+ * @param obj The scrolled entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_cursor_next(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return elm_entry_cursor_next(wd->entry);
+}
+
+/**
+ * This moves the cursor one place to the left within the entry.
+ *
+ * @param obj The scrolled entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_cursor_prev(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return elm_entry_cursor_prev(wd->entry);
+}
+
+/**
+ * This moves the cursor one line up within the entry.
+ *
+ * @param obj The scrolled entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_cursor_up(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return elm_entry_cursor_up(wd->entry);
+}
+
+/**
+ * This moves the cursor one line down within the entry.
+ *
+ * @param obj The scrolled entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_cursor_down(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return elm_entry_cursor_down(wd->entry);
+}
+
+/**
+ * This moves the cursor to the beginning of the entry.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_cursor_begin_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_cursor_begin_set(wd->entry);
+}
+
+/**
+ * This moves the cursor to the end of the entry.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_cursor_end_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   int x, y, w, h;
+   elm_entry_cursor_end_set(wd->entry);
+   elm_widget_show_region_get(wd->entry, &x, &y, &w, &h);
+   elm_scroller_region_show(wd->scroller, x, y, w, h);
+}
+
+/**
+ * This moves the cursor to the beginning of the current line.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_cursor_line_begin_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_cursor_line_begin_set(wd->entry);
+}
+
+/**
+ * This moves the cursor to the end of the current line.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_cursor_line_end_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_cursor_line_end_set(wd->entry);
+}
+
+/**
+ * This begins a selection within the scrolled entry as though
+ * the user were holding down the mouse button to make a selection.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_cursor_selection_begin(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_cursor_selection_begin(wd->entry);
+}
+
+/**
+ * This ends a selection within the scrolled entry as though
+ * the user had just released the mouse button while making a selection.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_cursor_selection_end(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_cursor_selection_end(wd->entry);
+}
+
+/**
+ * TODO: fill this in
+ *
+ * @param obj The scrolled entry object
+ * @return TODO: fill this in
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_cursor_is_format_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 elm_entry_cursor_is_format_get(wd->entry);
+}
+
+/**
+ * This returns whether the cursor is visible.
+ *
+ * @param obj The scrolled entry object
+ * @return If true, the cursor is visible.
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_cursor_is_visible_format_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 elm_entry_cursor_is_visible_format_get(wd->entry);
+}
+
+/**
+ * TODO: fill this in
+ *
+ * @param obj The scrolled entry object
+ * @return TODO: fill this in
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI const char *
+elm_scrolled_entry_cursor_content_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_entry_cursor_content_get(wd->entry);
+}
+
+/**
+ * This executes a "cut" action on the selected text in the scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_selection_cut(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_selection_cut(wd->entry);
+}
+
+/**
+ * This executes a "copy" action on the selected text in the scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_selection_copy(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_selection_copy(wd->entry);
+}
+
+/**
+ * This executes a "paste" action in the scrolled entry.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_selection_paste(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_selection_paste(wd->entry);
+}
+
+/**
+ * This clears and frees the items in a scrolled entry's contextual (right click) menu.
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_context_menu_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_context_menu_clear(wd->entry);
+}
+
+/**
+ * This adds an item to the scrolled entry's contextual menu.
+ *
+ * @param obj The scrolled entry object
+ * @param label The item's text label
+ * @param icon_file The item's icon file
+ * @param icon_type The item's icon type
+ * @param func The callback to execute when the item is clicked
+ * @param data The data to associate with the item for related functions
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_context_menu_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data)
+{
+   Elm_Entry_Context_Menu_Item *ci;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   ci = malloc(sizeof(Elm_Entry_Context_Menu_Item));
+   if (!ci) return;
+   ci->func = func;
+   ci->data = (void *)data;
+   ci->obj = obj;
+   wd->items = eina_list_append(wd->items, ci);
+   elm_entry_context_menu_item_add(wd->entry, label, icon_file, icon_type, _context_item_wrap_cb, ci);
+}
+
+/**
+ * This disables the scrolled entry's contextual (right click) menu.
+ *
+ * @param obj The scrolled entry object
+ * @param disabled If true, the menu is disabled
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_context_menu_disabled_set(wd->entry, disabled);
+}
+
+/**
+ * This returns whether the scrolled entry's contextual (right click) menu is disabled.
+ *
+ * @param obj The scrolled entry object
+ * @return If true, the menu is disabled
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_context_menu_disabled_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 elm_entry_context_menu_disabled_get(wd->entry);
+}
+
+/**
+ * This sets the scrolled entry's scrollbar policy (ie. enabling/disabling them).
+ *
+ * @param obj The scrolled entry object
+ * @param h The horizontal scrollbar policy to apply
+ * @param v The vertical scrollbar policy to apply
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->policy_h = h;
+   wd->policy_v = v;
+   elm_scroller_policy_set(wd->scroller, h, v);
+}
+
+/**
+ * This enables/disables bouncing within the entry.
+ *
+ * @param obj The scrolled entry object
+ * @param h The horizontal bounce state
+ * @param v The vertical bounce state
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_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->scroller, h_bounce, v_bounce);
+}
+
+/**
+ * Get the bounce mode
+ *
+ * @param obj The Scrolled_Entry object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_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_scroller_bounce_get(wd->scroller, h_bounce, v_bounce);
+}
+
+/**
+ * This appends a custom item provider to the list for that entry
+ *
+ * This appends the given callback. The list is walked from beginning to end
+ * with each function called given the item href string in the text. If the
+ * function returns an object handle other than NULL (it should create an
+ * and object to do this), then this object is used to replace that item. If
+ * not the next provider is called until one provides an item object, or the
+ * default provider in entry does.
+ *
+ * @param obj The entry object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_append(wd->item_providers, ip);
+}
+
+/**
+ * This prepends a custom item provider to the list for that entry
+ *
+ * This prepends the given callback. See elm_scrolled_entry_item_provider_append() for
+ * more information
+ *
+ * @param obj The entry object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_prepend(wd->item_providers, ip);
+}
+
+/**
+ * This removes a custom item provider to the list for that entry
+ *
+ * This removes the given callback. See elm_scrolled_entry_item_provider_append() for
+ * more information
+ *
+ * @param obj The entry object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Entry_Item_Provider *ip;
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        if ((ip->func == func) && (ip->data == data))
+          {
+             wd->item_providers = eina_list_remove_list(wd->item_providers, l);
+             free(ip);
+             return;
+          }
+     }
+}
+
+/**
+ * Append a filter function for text inserted in the entry
+ *
+ * Append the given callback to the list. This functions will be called
+ * whenever any text is inserted into the entry, with the text to be inserted
+ * as a parameter. The callback function is free to alter the text in any way
+ * it wants, but it must remember to free the given pointer and update it.
+ * If the new text is to be discarded, the function can free it and set it text
+ * parameter to NULL. This will also prevent any following filters from being
+ * called.
+ *
+ * @param obj The entry object
+ * @param func The function to use as text filter
+ * @param data User data to pass to @p func
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
+{
+   Widget_Data *wd;
+   Elm_Entry_Text_Filter *tf;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   wd = elm_widget_data_get(obj);
+
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   tf = ELM_NEW(Elm_Entry_Text_Filter);
+   if (!tf) return;
+   tf->func = func;
+   tf->data = data;
+   wd->text_filters = eina_list_append(wd->text_filters, tf);
+}
+
+/**
+ * Prepend a filter function for text insdrted in the entry
+ *
+ * Prepend the given callback to the list. See elm_scrolled_entry_text_filter_append()
+ * for more information
+ *
+ * @param obj The entry object
+ * @param func The function to use as text filter
+ * @param data User data to pass to @p func
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
+{
+   Widget_Data *wd;
+   Elm_Entry_Text_Filter *tf;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   wd = elm_widget_data_get(obj);
+
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   tf = ELM_NEW(Elm_Entry_Text_Filter);
+   if (!tf) return;
+   tf->func = func;
+   tf->data = data;
+   wd->text_filters = eina_list_prepend(wd->text_filters, tf);
+}
+
+/**
+ * Remove a filter from the list
+ *
+ * Removes the given callback from the filter list. See elm_scrolled_entry_text_filter_append()
+ * for more information.
+ *
+ * @param obj The entry object
+ * @param func The filter function to remove
+ * @param data The user data passed when adding the function
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
+{
+   Widget_Data *wd;
+   Eina_List *l;
+   Elm_Entry_Text_Filter *tf;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   wd = elm_widget_data_get(obj);
+
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   EINA_LIST_FOREACH(wd->text_filters, l, tf)
+     {
+        if ((tf->func == func) && (tf->data == data))
+          {
+             wd->text_filters = eina_list_remove_list(wd->text_filters, l);
+             free(tf);
+             return;
+          }
+     }
+}
+
+/**
+ * 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 entry object is set to autosave.
+ *
+ * @param obj The scrolled entry object
+ * @param file The path to the file to load and save
+ * @param format The file format
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_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;
+   elm_entry_file_set(wd->entry, file, format);
+}
+
+/**
+ * Gets the file to load and save and the file format
+ *
+ * @param obj The scrolled entry object
+ * @param file The path to the file to load and save
+ * @param format The file format
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_file_get(const 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;
+   elm_entry_file_get(wd->entry, file, format);
+}
+
+/**
+ * This function writes any changes made to the file set with
+ * elm_scrolled_entry_file_set()
+ *
+ * @param obj The scrolled entry object
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_file_save(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_file_save(wd->entry);
+}
+
+/**
+ * This sets the entry object to 'autosave' the loaded text file or not.
+ *
+ * @param obj The scrolled entry object
+ * @param autosave Autosave the loaded file or not
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI void
+elm_scrolled_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_entry_autosave_set(wd->entry, autosave);
+}
+
+/**
+ * This gets the entry object's 'autosave' status.
+ *
+ * @param obj The scrolled entry object
+ * @return Autosave the loaded file or not
+ *
+ * @ingroup Scrolled_Entry
+ */
+EAPI Eina_Bool
+elm_scrolled_entry_autosave_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 elm_entry_autosave_get(wd->entry);
+}
diff --git a/src/lib/elm_actionslider.c b/src/lib/elm_actionslider.c
new file mode 100644 (file)
index 0000000..2aafd7c
--- /dev/null
@@ -0,0 +1,546 @@
+/**
+ * @addtogroup Actionslider Actionslider
+ *
+ * A magnet slider is a switcher for 3 labels with customizable
+ * magnet properties. When the position is set with magnet, the knob
+ * will be moved to it if it's nearest the magnetized position.
+ *
+ * Signals emmitted:
+ * "selected" - when user selects a position (the label is passed as
+ * event info)".
+ * "pos_changed" - when a button reaches to the special position like
+ * "left", "right" and "center".
+ */
+
+#include <Elementary.h>
+#include <math.h>
+#include "elm_priv.h"
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *as;     // actionslider
+   Evas_Object *drag_button_base;
+   Elm_Actionslider_Pos magnet_position, enabled_position;
+   const char *text_left, *text_right, *text_center;
+   const char *indicator_label;
+   Ecore_Animator *button_animator;
+   double final_position;
+   Eina_Bool mouse_down : 1;
+};
+
+static const char *widtype = NULL;
+
+#define SIG_CHANGED "pos_changed"
+#define SIG_SELECTED "selected"
+
+static const Evas_Smart_Cb_Description _signals[] =
+{
+   {SIG_CHANGED, ""},
+   {SIG_SELECTED, ""},
+   {NULL, NULL}
+};
+
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->drag_button_base) 
+     {
+        evas_object_del(wd->drag_button_base);
+        wd->drag_button_base = NULL;
+     }
+   if (wd->text_left) eina_stringshare_del(wd->text_left);
+   if (wd->text_right) eina_stringshare_del(wd->text_right);
+   if (wd->text_center) eina_stringshare_del(wd->text_center);
+   if (wd->indicator_label) eina_stringshare_del(wd->indicator_label);
+   free(wd);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_size_hint_min_set(wd->drag_button_base, minw, minh);
+   evas_object_size_hint_max_set(wd->drag_button_base, -1, -1);
+
+   minw = -1;
+   minh = -1;
+   elm_coords_finger_size_adjust(3, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->as, &minw, &minh, minw, minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (!edje_object_part_swallow_get(wd->as, "elm.drag_button_base"))
+     edje_object_part_unswallow(wd->as, wd->drag_button_base);
+
+   _elm_theme_object_set(obj, wd->as, "actionslider",
+                         "base", elm_widget_style_get(obj));
+   _elm_theme_object_set(obj, wd->drag_button_base, "actionslider",
+                         "drag_button", elm_widget_style_get(obj));
+   edje_object_part_swallow(wd->as, "elm.drag_button_base", wd->drag_button_base);
+   edje_object_part_text_set(wd->as, "elm.text.left", wd->text_left);
+   edje_object_part_text_set(wd->as, "elm.text.right", wd->text_right);
+   edje_object_part_text_set(wd->as, "elm.text.center", wd->text_center);
+   edje_object_part_text_set(wd->as, "elm.text.indicator", wd->indicator_label);
+   edje_object_message_signal_process(wd->as);
+   _sizing_eval(obj);
+}
+
+static void
+_drag_button_down_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get((Evas_Object *) data);
+   if (!wd) return;
+   wd->mouse_down = EINA_TRUE;
+}
+
+static void
+_drag_button_move_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Evas_Object *as = (Evas_Object *) data;
+   Widget_Data *wd = elm_widget_data_get(as);
+   double pos = 0.0;
+   if (!wd) return;
+
+   if (!wd->mouse_down) return;
+   edje_object_part_drag_value_get(wd->as, "elm.drag_button_base", &pos, NULL);
+   if (pos == 0.0)
+     evas_object_smart_callback_call(as, SIG_CHANGED, "left");
+   else if (pos == 1.0)
+     evas_object_smart_callback_call(as, SIG_CHANGED, "right");
+   else if (pos >= 0.45 && pos <= 0.55)
+     evas_object_smart_callback_call(as, SIG_CHANGED, "center");
+}
+
+static Eina_Bool
+_button_animation(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   double cur_position = 0.0, new_position = 0.0;
+   double move_amount = 0.05;
+   Eina_Bool flag_finish_animation = EINA_FALSE;
+   if (!wd) return EINA_FALSE;
+
+   edje_object_part_drag_value_get(wd->as,
+                                   "elm.drag_button_base", &cur_position, NULL);
+   if ((wd->final_position == 0.0) ||
+       (wd->final_position == 0.5 && cur_position >= wd->final_position))
+     {
+        new_position = cur_position - move_amount;
+        if (new_position <= wd->final_position)
+          {
+             new_position = wd->final_position;
+             flag_finish_animation = EINA_TRUE;
+          }
+     }
+   else if ((wd->final_position == 1.0) ||
+            (wd->final_position == 0.5 && cur_position < wd->final_position))
+     {
+        new_position = cur_position + move_amount;
+        if (new_position >= wd->final_position)
+          {
+             new_position = wd->final_position;
+             flag_finish_animation = EINA_TRUE;
+          }
+     }
+   edje_object_part_drag_value_set(wd->as,
+                                   "elm.drag_button_base", new_position, 0.5);
+   if (flag_finish_animation)
+     {
+        if ((!wd->final_position) &&
+            (wd->enabled_position & ELM_ACTIONSLIDER_LEFT))
+          evas_object_smart_callback_call(data, SIG_SELECTED,
+                                          (void *)wd->text_left);
+        else if ((wd->final_position == 0.5) &&
+                 (wd->enabled_position & ELM_ACTIONSLIDER_CENTER))
+          evas_object_smart_callback_call(data, SIG_SELECTED,
+                                          (void *)wd->text_center);
+        else if ((wd->final_position == 1) &&
+                 (wd->enabled_position & ELM_ACTIONSLIDER_RIGHT))
+          evas_object_smart_callback_call(data, SIG_SELECTED,
+                                          (void *)wd->text_right);
+        return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+
+static void
+_drag_button_up_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   double position = 0.0;
+   if (!wd) return;
+
+   wd->mouse_down = EINA_FALSE;
+
+   edje_object_part_drag_value_get(wd->as, "elm.drag_button_base",
+                                   &position, NULL);
+
+   if (position == 0.0 && (wd->enabled_position & ELM_ACTIONSLIDER_LEFT))
+     {
+        wd->final_position = 0;
+        evas_object_smart_callback_call(data, SIG_SELECTED,
+                                        (void *)wd->text_left);
+        return;
+     }
+   if (position >= 0.45 && position <= 0.55 &&
+       (wd->enabled_position & ELM_ACTIONSLIDER_CENTER))
+     {
+        wd->final_position = 0.5;
+        evas_object_smart_callback_call(data, SIG_SELECTED,
+                                        (void *)wd->text_center);
+        return;
+     }
+   if (position == 1.0 && (wd->enabled_position & ELM_ACTIONSLIDER_RIGHT))
+     {
+        wd->final_position = 1;
+        evas_object_smart_callback_call(data, SIG_SELECTED,
+                                        (void *)wd->text_right);
+        return;
+     }
+
+   if (wd->magnet_position == ELM_ACTIONSLIDER_NONE) return;
+
+   if (position < 0.3)
+     {
+        if (wd->magnet_position & ELM_ACTIONSLIDER_LEFT)
+          wd->final_position = 0;
+        else if (wd->magnet_position & ELM_ACTIONSLIDER_CENTER)
+          wd->final_position = 0.5;
+        else if (wd->magnet_position & ELM_ACTIONSLIDER_RIGHT)
+          wd->final_position = 1;
+     }
+   else if ((position >= 0.3) && (position <= 0.7))
+     {
+        if (wd->magnet_position & ELM_ACTIONSLIDER_CENTER)
+          wd->final_position = 0.5;
+        else if (position < 0.5)
+          {
+             if (wd->magnet_position & ELM_ACTIONSLIDER_LEFT)
+               wd->final_position = 0;
+             else
+               wd->final_position = 1;
+          }
+        else
+          {
+             if (wd->magnet_position & ELM_ACTIONSLIDER_RIGHT)
+               wd->final_position = 1;
+             else
+               wd->final_position = 0;
+          }
+     }
+   else
+     {
+        if (wd->magnet_position & ELM_ACTIONSLIDER_RIGHT)
+          wd->final_position = 1;
+        else if (wd->magnet_position & ELM_ACTIONSLIDER_CENTER)
+          wd->final_position = 0.5;
+        else
+          wd->final_position = 0;
+     }
+   wd->button_animator = ecore_animator_add(_button_animation, data);
+}
+
+/**
+ * Add a new actionslider to the parent.
+ *
+ * @param parent The parent object
+ * @return The new actionslider object or NULL if it cannot be created
+ *
+ * @ingroup Actionslider
+ */
+EAPI Evas_Object *
+elm_actionslider_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Widget_Data *wd;
+   Evas *e;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "actionslider");
+   elm_widget_type_set(obj, "actionslider");
+   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->mouse_down = EINA_FALSE;
+   wd->enabled_position = ELM_ACTIONSLIDER_ALL;
+
+   wd->as = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->as, "actionslider", "base", "default");
+   elm_widget_resize_object_set(obj, wd->as);
+
+   wd->drag_button_base = evas_object_rectangle_add(e);
+   evas_object_color_set(wd->drag_button_base, 0, 0, 0, 0);
+   edje_object_part_swallow(wd->as, "elm.drag_button_base", wd->drag_button_base);
+
+   edje_object_signal_callback_add(wd->as,
+                                   "elm.drag_button,mouse,up", "",
+                                   _drag_button_up_cb, obj);
+   edje_object_signal_callback_add(wd->as,
+                                   "elm.drag_button,mouse,down", "",
+                                   _drag_button_down_cb, obj);
+   edje_object_signal_callback_add(wd->as,
+                                   "elm.drag_button,mouse,move", "",
+                                   _drag_button_move_cb, obj);
+
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set actionslider indicator position.
+ *
+ * @param obj The actionslider object.
+ * @param pos The position of the indicator.
+ *
+ * @ingroup Actionslider
+ */
+EAPI void
+elm_actionslider_indicator_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double position = 0.0;
+   if (!wd) return;
+   if (pos == ELM_ACTIONSLIDER_CENTER) position = 0.5;
+   else if (pos == ELM_ACTIONSLIDER_RIGHT) position = 1.0;
+   edje_object_part_drag_value_set(wd->as, "elm.drag_button_base", position, 0.5);
+}
+
+/**
+ * Get actionslider indicator position.
+ *
+ * @param obj The actionslider object.
+ * @return The position of the indicator.
+ *
+ * @ingroup Actionslider
+ */
+EAPI Elm_Actionslider_Pos
+elm_actionslider_indicator_pos_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_ACTIONSLIDER_NONE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double position;
+   if (!wd) return ELM_ACTIONSLIDER_NONE;
+
+   edje_object_part_drag_value_get(wd->as, "elm.drag_button_base", &position, NULL);
+   if (position < 0.3)
+     return ELM_ACTIONSLIDER_LEFT;
+   else if (position < 0.7)
+     return ELM_ACTIONSLIDER_CENTER;
+   else
+     return ELM_ACTIONSLIDER_RIGHT;
+}
+
+/**
+ * Set actionslider magnet position.
+ *
+ * @param obj The actionslider object.
+ * @param pos Bit mask indicating the magnet positions.
+ * Example: use (ELM_ACTIONSLIDER_LEFT | ELM_ACTIONSLIDER_RIGHT)
+ * to put magnet property on both positions
+ *
+ * @ingroup Actionslider
+ */
+EAPI void
+elm_actionslider_magnet_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->magnet_position = pos;
+}
+
+/**
+ * Get actionslider magnet position.
+ *
+ * @param obj The actionslider object.
+ * @return The positions with magnet property.
+ *
+ * @ingroup Actionslider
+ */
+EAPI Elm_Actionslider_Pos
+elm_actionslider_magnet_pos_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_ACTIONSLIDER_NONE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_ACTIONSLIDER_NONE;
+   return wd->magnet_position;
+}
+
+/**
+ * Set actionslider enabled position.
+ *
+ * All the positions are enabled by default.
+ *
+ * @param obj The actionslider object.
+ * @param pos Bit mask indicating the enabled positions.
+ * Example: use (ELM_ACTIONSLIDER_LEFT | ELM_ACTIONSLIDER_RIGHT)
+ * to enable both positions, so the user can select it.
+ *
+ * @ingroup Actionslider
+ */
+EAPI void
+elm_actionslider_enabled_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->enabled_position = pos;
+}
+
+/**
+ * Get actionslider enabled position.
+ *
+ * All the positions are enabled by default.
+ *
+ * @param obj The actionslider object.
+ * @return The enabled positions.
+ *
+ * @ingroup Actionslider
+ */
+EAPI Elm_Actionslider_Pos
+elm_actionslider_enabled_pos_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_ACTIONSLIDER_NONE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_ACTIONSLIDER_NONE;
+   return wd->enabled_position;
+}
+
+/**
+ * Set actionslider labels.
+ *
+ * @param obj The actionslider object
+ * @param left_label The label which is going to be set.
+ * @param center_label The label which is going to be set.
+ * @param right_label The label which is going to be set.
+ *
+ * @ingroup Actionslider
+ */
+EAPI void
+elm_actionslider_labels_set(Evas_Object *obj, const char *left_label, const char *center_label, const char *right_label)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   eina_stringshare_replace(&wd->text_left, left_label);
+   edje_object_part_text_set(wd->as, "elm.text.left", left_label);
+   eina_stringshare_replace(&wd->text_center, center_label);
+   edje_object_part_text_set(wd->as, "elm.text.center", center_label);
+   eina_stringshare_replace(&wd->text_right, right_label);
+   edje_object_part_text_set(wd->as, "elm.text.right", right_label);
+}
+
+/**
+ * Get actionslider labels.
+ *
+ * @param obj The actionslider object
+ * @param left_label A char** to place the left_label of @p obj into
+ * @param center_label A char** to place the center_label of @p obj into
+ * @param right_label A char** to place the right_label of @p obj into
+ *
+ * @ingroup Actionslider
+ */
+EAPI void
+elm_actionslider_labels_get(const Evas_Object *obj, const char **left_label, const char **center_label, const char **right_label)
+{
+   if (left_label) *left_label= NULL;
+   if (center_label) *center_label= NULL;
+   if (right_label) *right_label= NULL;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (left_label) *left_label = wd->text_left;
+   if (center_label) *center_label = wd->text_center;
+   if (right_label) *right_label = wd->text_right;
+}
+
+/**
+ * Get actionslider selected label.
+ *
+ * @param obj The actionslider object
+ * @return The selected label
+ *
+ * @ingroup Actionslider
+ */
+EAPI const char *
+elm_actionslider_selected_label_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->final_position == 0.0) &&
+       (wd->enabled_position & ELM_ACTIONSLIDER_LEFT))
+     return wd->text_left;
+
+   if ((wd->final_position == 0.5) &&
+       (wd->enabled_position & ELM_ACTIONSLIDER_CENTER))
+     return wd->text_center;
+
+   if ((wd->final_position == 1.0) &&
+       (wd->enabled_position & ELM_ACTIONSLIDER_RIGHT))
+     return wd->text_right;
+
+   return NULL;
+}
+
+/**
+ * Set the label used on the indicator object.
+ *
+ * @param obj The actionslider object
+ * @param label The label which is going to be set.
+ *
+ * @ingroup Actionslider
+ */
+EAPI void 
+elm_actionslider_indicator_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->indicator_label, label);
+   edje_object_part_text_set(wd->as, "elm.text.indicator", wd->indicator_label);
+}
+
+/**
+ * Get the label used on the indicator object.
+ *
+ * @param obj The actionslider object
+ * @return The indicator label
+ *
+ * @ingroup Actionslider
+ */
+EAPI const char *
+elm_actionslider_indicator_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->indicator_label;
+}
diff --git a/src/lib/elm_animator.c b/src/lib/elm_animator.c
new file mode 100644 (file)
index 0000000..1c642c8
--- /dev/null
@@ -0,0 +1,446 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define ELM_ANIMATOR_CHECK_OR_RETURN(animator, ...) \
+   do { \
+      if (!animator) { \
+         CRITICAL("Elm_Animator " # animator " is NULL!"); \
+         return __VA_ARGS__; \
+      } \
+      if (!EINA_MAGIC_CHECK(animator, ELM_ANIMATOR_MAGIC)) { \
+         EINA_MAGIC_FAIL(animator, ELM_ANIMATOR_MAGIC); \
+         return __VA_ARGS__; \
+      } \
+   } while (0)
+
+
+/**
+ * @addtogroup Animator Animator
+ * @ingroup Elementary
+ *
+ * elm_animator is designed to provides animation frame.
+ * It is somewhat different with any others widgets however elm_animator
+ * might useful when your GUIs have animation.
+ * Basically, it computes normalized frame value for animation,
+ * provides additional functions to adjust this also.
+ *
+ */
+
+struct _Elm_Animator
+{
+#define ELM_ANIMATOR_MAGIC 0x40777770
+   EINA_MAGIC;
+
+   Evas_Object *parent;
+   Ecore_Animator *animator;
+   double begin_time;
+   double cur_time;
+   double duration;
+   unsigned int repeat_cnt;
+   unsigned int cur_repeat_cnt;
+   void (*animator_op) (void *data, Elm_Animator *animator, double frame);
+   void *animator_arg;
+   void (*completion_op) (void *data);
+   void *completion_arg;
+   Elm_Animator_Curve_Style curve_style;
+   Eina_Bool auto_reverse:1;
+   Eina_Bool on_animating:1;
+};
+
+static double _animator_curve_linear(double frame);
+static double _animator_curve_in_out(double frame);
+static double _animator_curve_in(double frame);
+static double _animator_curve_out(double frame);
+static unsigned int _animator_compute_reverse_repeat_count(unsigned int cnt);
+static unsigned int _animator_compute_no_reverse_repeat_count(unsigned int cnt);
+static Eina_Bool _animator_animate_cb(void *data);
+static void _delete_animator(Elm_Animator *animator);
+static void _animator_parent_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__);
+
+static unsigned int
+_animator_compute_reverse_repeat_count(unsigned int cnt)
+{
+   return ((cnt + 1) * 2) - 1;
+}
+
+static unsigned int
+_animator_compute_no_reverse_repeat_count(unsigned int cnt)
+{
+   return cnt / 2;
+}
+
+static double
+_animator_curve_linear(double frame)
+{
+   return frame;
+}
+
+static double
+_animator_curve_in_out(double frame)
+{
+   if (frame < 0.5) return _animator_curve_in(frame * 2) * 0.5;
+   else return (_animator_curve_out(frame * 2 - 1) * 0.5) + 0.5;
+}
+
+static double
+_animator_curve_in(double frame)
+{
+   return 1 - sqrt(1 - pow(frame, 2));
+}
+
+static double
+_animator_curve_out(double frame)
+{
+   return sqrt(1 - pow(frame - 1, 2));
+}
+
+static void
+_delete_animator(Elm_Animator *animator)
+{
+   if (!animator->animator) return;
+   ecore_animator_del(animator->animator);
+   animator->animator = NULL;
+}
+
+static Eina_Bool
+_animator_animate_cb(void *data)
+{
+   double elapsed_time, frame;
+   Elm_Animator *animator = (Elm_Animator *) data;
+
+   animator->cur_time = ecore_loop_time_get();
+   elapsed_time = animator->cur_time - animator->begin_time;
+   if (elapsed_time > animator->duration) elapsed_time = animator->duration;
+
+   //Compute current frame
+   switch (animator->curve_style)
+     {
+       case ELM_ANIMATOR_CURVE_IN_OUT:
+             frame = _animator_curve_in_out(elapsed_time / animator->duration);
+             break;
+       case ELM_ANIMATOR_CURVE_IN:
+             frame = _animator_curve_in(elapsed_time / animator->duration);
+             break;
+       case ELM_ANIMATOR_CURVE_OUT:
+             frame = _animator_curve_out(elapsed_time / animator->duration);
+             break;
+       default:
+         frame = _animator_curve_linear(elapsed_time / animator->duration);
+             break;
+     }
+       
+   //Reverse?
+   if (animator->auto_reverse)
+     {
+       if (!(animator->cur_repeat_cnt % 2)) frame = 1 - frame;
+     }
+
+   if (animator->duration > 0)
+      animator->animator_op(animator->animator_arg, animator, frame);
+   //Not end. Keep going.
+   if (elapsed_time < animator->duration) return ECORE_CALLBACK_RENEW;
+
+   //Repeat and reverse and time done!
+   if (!animator->cur_repeat_cnt)
+     {
+       animator->on_animating = EINA_FALSE;
+       _delete_animator(animator);
+       if (animator->completion_op)
+          animator->completion_op(animator->completion_arg);
+       return ECORE_CALLBACK_CANCEL;
+     }
+
+   //Repeat Case
+   animator->cur_repeat_cnt--;
+   animator->begin_time = ecore_loop_time_get();
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_animator_parent_del(void *data, Evas *evas __UNUSED__,
+                    Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   elm_animator_del(data);
+}
+
+/**
+ * Get the value of reverse mode.
+ *
+ * @param[in] animator Animator object
+ * @return EINA_TRUE is reverse mode
+ *
+ * @ingroup Animator
+ */
+EAPI Eina_Bool
+elm_animator_auto_reverse_get(const Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator, EINA_FALSE);
+   return animator->auto_reverse;
+}
+
+/**
+ * Get the value of repeat count.
+ *
+ * @param[in] animator Animator object
+ * @return Repeat count
+ *
+ * @ingroup Animator
+ */
+EAPI unsigned int
+elm_animator_repeat_get(const Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator, 0);
+   return animator->repeat_cnt;
+}
+
+/**
+ * Set the animation acceleration style.
+ *
+ * @param[in] animator Animator object
+ * @param[in] cs Curve style. Default is ELM_ANIMATOR_CURVE_LINEAR
+ *
+ * @ingroup Animator
+ */
+EAPI Elm_Animator_Curve_Style 
+elm_animator_curve_style_get(const Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator, ELM_ANIMATOR_CURVE_LINEAR);
+  
+       return animator->curve_style;
+}
+
+/**
+ * Set auto reverse function.
+ *
+ * @param[in] animator Animator object
+ * @param[in] reverse Reverse or not
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (animator->auto_reverse == reverse) return;
+   animator->auto_reverse = reverse;
+   if (reverse)
+      animator->repeat_cnt =
+        _animator_compute_reverse_repeat_count(animator->repeat_cnt);
+   else
+      animator->repeat_cnt =
+        _animator_compute_no_reverse_repeat_count(animator->repeat_cnt);
+}
+
+/**
+ * Set the animation acceleration style.
+ *
+ * @param[in] animator Animator object
+ * @param[in] cs Curve style. Default is ELM_ANIMATOR_CURVE_LINEAR
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_curve_style_set(Elm_Animator *animator,
+                            Elm_Animator_Curve_Style cs)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+
+       animator->curve_style = cs;
+}
+
+/**
+ * Set the operation duration.
+ *
+ * @param[in] animator Animator object
+ * @param[in] duration Duration in second
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_duration_set(Elm_Animator *animator, double duration)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (animator->on_animating) return;
+   animator->duration = duration;
+}
+
+/**
+ * Set the callback function for animator operation.
+ * The range of callback function frame data is to 0 ~ 1
+ * User can refer this frame value for one's animation frame data.
+ * @param[in] animator Animator object
+ * @param[in] func Callback function pointer
+ * @param[in] data Callback function user argument
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_operation_callback_set(Elm_Animator *animator,
+                                    Elm_Animator_Operation_Cb func,
+                                    void *data)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (animator->on_animating) return;
+   animator->animator_op = func;
+   animator->animator_arg = data;
+}
+
+/**
+ * Add new animator.
+ *
+ * @param[in] parent Parent object
+ * @return animator object
+ *
+ * @ingroup Animator
+ */
+EAPI Elm_Animator *
+elm_animator_add(Evas_Object *parent)
+{
+   Elm_Animator *animator = ELM_NEW(Elm_Animator);
+   if (!animator) return NULL;
+   EINA_MAGIC_SET(animator, ELM_ANIMATOR_MAGIC);
+   animator->parent = parent;
+   elm_animator_auto_reverse_set(animator, EINA_FALSE);
+   elm_animator_curve_style_set(animator, ELM_ANIMATOR_CURVE_LINEAR);
+   if (parent)
+      evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
+                                    _animator_parent_del, animator);
+   return animator;
+}
+
+/**
+ * Get the status for the animator operation.
+ *
+ * @param[in] animator Animator object
+ * @return EINA_TRUE is animator is operating.
+ *
+ * @ingroup Animator
+ */
+EAPI Eina_Bool
+elm_animator_operating_get(const Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator, EINA_FALSE);
+   return animator->on_animating;
+}
+
+/**
+ * Delete animator.
+ *
+ * @param[in] animator Animator object
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_del(Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   _delete_animator(animator);
+   if (animator->parent)
+      evas_object_event_callback_del(animator->parent, EVAS_CALLBACK_DEL,
+                                    _animator_parent_del);
+
+   EINA_MAGIC_SET(animator, EINA_MAGIC_NONE);
+   free(animator);
+}
+
+/**
+ * Set the callback function for the animator end.
+ *
+ * @param[in]  animator Animator object
+ * @param[in]  func   Callback function pointe
+ * @param[in]  data Callback function user argument
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_completion_callback_set(Elm_Animator *animator,
+                                    Elm_Animator_Completion_Cb func,
+                                     void *data)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (animator->on_animating) return;
+   animator->completion_op = func;
+   animator->completion_arg = data;
+}
+
+/**
+ * Pause the animator.
+ *
+ * @param[in]  animator Animator object
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_pause(Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (!animator->on_animating) return;
+   ecore_animator_freeze(animator->animator);
+}
+
+/**
+ * Resume the animator.
+ *
+ * @param[in]  animator Animator object
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_resume(Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (!animator->on_animating) return;
+   ecore_animator_thaw(animator->animator);
+}
+
+/**
+ * Stop animator.
+ *
+ * @param[in] animator Animator object
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_stop(Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   animator->on_animating = EINA_FALSE;
+   _delete_animator(animator);
+}
+
+/**
+ * Set the animator repeat count.
+ *
+ * @param[in]  animator Animator object
+ * @param[in]  repeat_cnt Repeat count
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (!animator->auto_reverse) animator->repeat_cnt = repeat_cnt;
+   else
+      animator->repeat_cnt = _animator_compute_reverse_repeat_count(repeat_cnt);
+}
+
+/**
+ * Animate now.
+ *
+ * @param[in] animator Animator object
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_animate(Elm_Animator *animator)
+{
+   ELM_ANIMATOR_CHECK_OR_RETURN(animator);
+   if (!animator->animator_op) return;
+   animator->begin_time = ecore_loop_time_get();
+   animator->cur_repeat_cnt = animator->repeat_cnt;
+   if (!animator->animator)
+      animator->animator = ecore_animator_add(_animator_animate_cb, animator);
+   if (animator->animator) animator->on_animating = EINA_TRUE;
+}
diff --git a/src/lib/elm_bg.c b/src/lib/elm_bg.c
new file mode 100644 (file)
index 0000000..50dd1e0
--- /dev/null
@@ -0,0 +1,398 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Bg Bg
+ *
+ * The bg object is used for setting a solid background to a window or packing
+ * into any container object.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *base, *rect, *img, *overlay;
+   const char  *file, *group;
+   Elm_Bg_Option option;
+};
+
+static const char *widtype = NULL;
+
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _custom_resize(void *data, Evas *a, Evas_Object *obj, void *event_info);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord w, h;
+
+   _elm_theme_object_set(obj, wd->base, "bg", "base", 
+                         elm_widget_style_get(obj));
+
+   if (wd->rect)
+     edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
+   if (wd->img)
+     edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
+   if (wd->overlay)
+     edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
+
+// FIXME: if i don't do this, bg doesnt calc correctly. why?   
+   evas_object_geometry_get(wd->base, NULL, NULL, &w, &h);
+   evas_object_resize(wd->base, w, h);
+}
+
+static void
+_custom_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = data;
+   Evas_Coord bx = 0, by = 0, bw = 0, bh = 0;
+   Evas_Coord iw = 0, ih = 0, mw = -1, mh = -1;
+   Evas_Coord fx = 0, fy = 0, fw = 0, fh = 0;
+   Evas_Coord nx = 0, ny = 0, nw = 0, nh = 0;
+   const char *p;
+
+   if ((!wd->img) || (!wd->file)) return;
+   if (((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))) return;
+
+   /* grab image size */
+   evas_object_image_size_get(wd->img, &iw, &ih);
+   if ((iw < 1) || (ih < 1)) return;
+
+   /* grab base object dimensions */
+   evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
+
+   /* set some defaults */
+   nx = bx;
+   ny = by;
+   nw = bw;
+   nh = bh;
+
+   switch (wd->option) 
+     {
+      case ELM_BG_OPTION_CENTER:
+        fw = nw = iw;
+        fh = nh = ih;
+        nx = ((bw - fw) / 2);
+        ny = ((bh - fh) / 2);
+        mw = iw;
+        mh = ih;
+        break;
+      case ELM_BG_OPTION_SCALE:
+        fw = bw;
+        fh = ((ih * fw) / iw);
+        if (fh < bh)
+          {
+             fh = bh;
+             fw = ((iw * fh) / ih);
+          }
+        fx = ((bw - fw) / 2);
+        fy = ((bh - fh) / 2);
+        break;
+      case ELM_BG_OPTION_TILE:
+        fw = iw;
+        fh = ih;
+        break;
+      case ELM_BG_OPTION_STRETCH:
+      default:
+        fw = bw;
+        fh = bh;
+        break;
+     }
+
+   evas_object_move(wd->img, nx, ny);
+   evas_object_resize(wd->img, nw, nh);
+   evas_object_image_fill_set(wd->img, fx, fy, fw, fh);
+
+   evas_object_size_hint_min_set(wd->img, mw, mh);
+   evas_object_size_hint_max_set(wd->img, mw, mh);
+}
+
+/**
+ * Add a new background to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Bg
+ */
+EAPI Evas_Object *
+elm_bg_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "bg");
+   elm_widget_type_set(obj, "bg");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->base = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->base, "bg", "base", "default");
+   elm_widget_resize_object_set(obj, wd->base);
+
+   evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE, 
+                                  _custom_resize, wd);
+
+   wd->option = ELM_BG_OPTION_SCALE;
+   return obj;
+}
+
+/**
+ * Set the file (image or edje) used for the background
+ *
+ * @param obj The bg object
+ * @param file The file path
+ * @param group Optional key (group in Edje) within the file
+ *
+ * This sets the image file used in the background object. The image (or edje)
+ * will be stretched (retaining aspect if its an image file) to completely fill
+ * the bg object. This may mean some parts are not visible.
+ *
+ * @note  Once the image of @p obj is set, a previously set one will be deleted,
+ * even if @p file is NULL.
+ *
+ * @ingroup Bg
+ */
+EAPI void
+elm_bg_file_set(Evas_Object *obj, const char *file, const char *group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *p;
+
+   if (wd->img)
+     {
+       evas_object_del(wd->img);
+       wd->img = NULL;
+     }
+   if (!file)
+     {
+        eina_stringshare_del(wd->file);
+        wd->file = NULL;
+        eina_stringshare_del(wd->group);
+        wd->group = NULL;
+        return;
+     }
+   eina_stringshare_replace(&wd->file, file);
+   eina_stringshare_replace(&wd->group, group);
+   if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
+     {
+       wd->img = edje_object_add(evas_object_evas_get(wd->base));
+       edje_object_file_set(wd->img, file, group);
+     }
+   else
+     {
+       wd->img = evas_object_image_add(evas_object_evas_get(wd->base));
+       evas_object_image_file_set(wd->img, file, group);
+     }
+   evas_object_repeat_events_set(wd->img, EINA_TRUE);
+   edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
+   elm_widget_sub_object_add(obj, wd->img);
+   _custom_resize(wd, NULL, NULL, NULL);
+}
+
+/**
+ * Get the file (image or edje) used for the background
+ *
+ * @param obj The bg object
+ * @param file The file path
+ * @param group Optional key (group in Edje) within the file
+ *
+ * @ingroup Bg
+ */
+EAPI void
+elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (file) *file = wd->file;
+   if (group) *group = wd->group;
+}
+
+/**
+ * Set the option used for the background image
+ *
+ * @param obj The bg object
+ * @param option The desired background option (TILE, SCALE)
+ *
+ * This sets the option used for manipulating the display of the background 
+ * image. The image can be tiled or scaled.
+ *
+ * @ingroup Bg
+ */
+EAPI void 
+elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option) 
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   wd->option = option;
+   _custom_resize(wd, NULL, NULL, NULL);
+}
+
+/**
+ * Get the option used for the background image
+ *
+ * @param obj The bg object
+ * @return The desired background option (TILE, SCALE)
+ *
+ * @ingroup Bg
+ */
+EAPI Elm_Bg_Option
+elm_bg_option_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   return wd->option;
+}
+
+/**
+ * Set the option used for the background color
+ *
+ * @param obj The bg object
+ * @param r
+ * @param g
+ * @param b
+ *
+ * This sets the color used for the background rectangle.
+ *
+ * @ingroup Bg
+ */
+EAPI void 
+elm_bg_color_set(Evas_Object *obj, int r, int g, int b) 
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd->rect)
+     {
+        wd->rect = evas_object_rectangle_add(evas_object_evas_get(wd->base));
+        edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
+        elm_widget_sub_object_add(obj, wd->rect);
+        _custom_resize(wd, NULL, NULL, NULL);
+     }
+   evas_object_color_set(wd->rect, r, g, b, 255);
+}
+
+/**
+ * Get the option used for the background color
+ *
+ * @param obj The bg object
+ * @param r
+ * @param g
+ * @param b
+ *
+ * @ingroup Bg
+ */
+EAPI void
+elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   evas_object_color_get(wd->rect, r, g, b, NULL);
+}
+
+/**
+ * Set the overlay object used for the background object.
+ *
+ * @param obj The bg object
+ * @param overlay The overlay object
+ *
+ * This provides a way for elm_bg to have an 'overlay' (such as animated fog)
+ * Once the over object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_bg_overlay_unset() function.
+ *
+ * @ingroup Bg
+ */
+EAPI void
+elm_bg_overlay_set(Evas_Object *obj, Evas_Object *overlay)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->overlay)
+     {
+       evas_object_del(wd->overlay);
+       wd->overlay = NULL;
+     }
+   if (overlay)
+     {
+        wd->overlay = overlay;
+        edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
+        elm_widget_sub_object_add(obj, wd->overlay);
+     }
+
+   _custom_resize(wd, NULL, NULL, NULL);
+}
+
+/**
+ * Set the overlay object used for the background object.
+ *
+ * @param obj The bg object
+ * @return The content that is being used
+ *
+ * Return the content object which is set for this widget
+ *
+ * @ingroup Bg
+ */
+EAPI Evas_Object *
+elm_bg_overlay_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->overlay;
+}
+
+/**
+ * Get the overlay object used for the background object.
+ *
+ * @param obj The bg object
+ * @return The content that was being used
+ *
+ * Unparent and return the overlay object which was set for this widget
+ *
+ * @ingroup Bg
+ */
+EAPI Evas_Object *
+elm_bg_overlay_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *overlay;
+   if (!wd) return NULL;
+   if (!wd->overlay) return NULL;
+   overlay = wd->overlay;
+   elm_widget_sub_object_del(obj, wd->overlay);
+   edje_object_part_unswallow(wd->base, wd->overlay);
+   wd->overlay = NULL;
+   _custom_resize(wd, NULL, NULL, NULL);
+   return overlay;
+}
diff --git a/src/lib/elm_box.c b/src/lib/elm_box.c
new file mode 100644 (file)
index 0000000..0d6449d
--- /dev/null
@@ -0,0 +1,894 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define SIG_CHILD_ADDED "child,added"
+#define SIG_CHILD_REMOVED "child,removed"
+
+/**
+ * @defgroup Box Box
+ *
+ * A box object arranges objects in a single row within a box. Sub objects can
+ * be added at the start, end or before or after any existing object in the
+ * box already. It can have its orientation changed too. How a child object is
+ * sized and otherwise arranged within the box depends on evas hints.
+ * evas_object_size_hint_align_set() will set either the alignment within its
+ * region if the region allocated is bigger than the object size. If you want
+ * the sub object sized up to fill the allocated region, use -1.0 for the
+ * apporpriate horizontal or vertical axes. evas_object_size_hint_weight_set()
+ * will set the packing weight. The weights of all items being packed are added
+ * up and if items are to be sized up to fit, those with the higher weights get
+ * proportionally more space.
+ *
+ * NOTE: Objects should not be added to box objects using _add() calls.
+ */
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Transition_Animation_Data Transition_Animation_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *box;
+   Eina_Bool horizontal:1;
+   Eina_Bool homogeneous:1;
+};
+
+struct _Elm_Box_Transition
+{
+   double initial_time;
+   double duration;
+   Eina_Bool animation_ended:1;
+   Eina_Bool recalculate:1;
+   Ecore_Animator *animator;
+
+   struct
+   {
+      Evas_Object_Box_Layout layout;
+      void *data;
+      void(*free_data)(void *data);
+   } start, end;
+
+   void(*transition_end_cb)(void *data);
+   void *transition_end_data;
+   void (*transition_end_free_data)(void *data);
+   Eina_List *objs;
+   Evas_Object *box;
+};
+
+struct _Transition_Animation_Data
+{
+   Evas_Object *obj;
+   struct
+   {
+      Evas_Coord x, y, w, h;
+   } start, end;
+};
+
+static const char *widtype = NULL;
+static void _del_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_pre_hook(Evas_Object *obj)
+{
+    Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+    evas_object_event_callback_del_full
+        (wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+    evas_object_box_remove_all(wd->box, 0);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   free(wd);
+}
+
+static void *
+_elm_box_list_data_get(const Eina_List *list)
+{
+   Evas_Object_Box_Option *opt = eina_list_data_get(list);
+   return opt->obj;
+}
+
+static Eina_Bool
+_elm_box_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *items;
+   void *(*list_data_get) (const Eina_List *list);
+
+   if ((!wd) || (!wd->box))
+     return EINA_FALSE;
+
+   /* Focus chain */
+   /* TODO: Change this to use other chain */
+   if ((items = elm_widget_focus_custom_chain_get(obj)))
+     list_data_get = eina_list_data_get;
+   else
+     {
+        Evas_Object_Box_Data *bd = evas_object_smart_data_get(wd->box);
+        items = bd->children;
+        list_data_get = _elm_box_list_data_get;
+
+        if (!items) return EINA_FALSE;
+     }
+
+   return elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
+}
+
+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;
+   evas_object_size_hint_min_get(wd->box, &minw, &minh);
+   evas_object_size_hint_max_get(wd->box, &maxw, &maxh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+   evas_object_geometry_get(obj, 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);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   _sizing_eval(obj);
+}
+
+static void
+_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
+{
+   Widget_Data *wd = data;
+   if (!wd) return;
+   _els_box_layout(o, priv, wd->horizontal, wd->homogeneous);
+}
+
+static Eina_Bool
+_transition_animation(void *data)
+{
+   evas_object_smart_changed(data);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_transition_layout_child_added(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Transition_Animation_Data *tad;
+   Evas_Object_Box_Option *opt = event_info;
+   Elm_Box_Transition *layout_data = data;
+
+   tad = calloc(1, sizeof(Transition_Animation_Data));
+   if (!tad) return;
+   tad->obj = opt->obj;
+   layout_data->objs = eina_list_append(layout_data->objs, tad);
+   layout_data->recalculate = EINA_TRUE;
+}
+
+static void
+_transition_layout_child_removed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Eina_List *l;
+   Transition_Animation_Data *tad;
+   Elm_Box_Transition *layout_data = data;
+
+   EINA_LIST_FOREACH(layout_data->objs, l, tad)
+     {
+        if (tad->obj == event_info)
+          {
+             free(eina_list_data_get(l));
+             layout_data->objs = eina_list_remove_list(layout_data->objs, l);
+             layout_data->recalculate = EINA_TRUE;
+             break;
+          }
+     }
+}
+
+static void
+_transition_layout_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Box_Transition *layout_data = data;
+   layout_data->recalculate = EINA_TRUE;
+}
+
+static void
+_transition_layout_calculate_coords(Evas_Object *obj, Evas_Object_Box_Data *priv,
+                                    Elm_Box_Transition *layout_data)
+{
+   Eina_List *l;
+   Transition_Animation_Data *tad;
+   Evas_Coord x, y, w, h;
+   const double curtime = ecore_loop_time_get();
+
+   layout_data->duration = 
+     layout_data->duration - (curtime - layout_data->initial_time);
+   layout_data->initial_time = curtime;
+
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   EINA_LIST_FOREACH(layout_data->objs, l, tad)
+     {
+        evas_object_geometry_get(tad->obj, &tad->start.x, &tad->start.y,
+                                 &tad->start.w, &tad->start.h);
+        tad->start.x = tad->start.x - x;
+        tad->start.y = tad->start.y - y;
+     }
+   layout_data->end.layout(obj, priv, layout_data->end.data);
+   EINA_LIST_FOREACH(layout_data->objs, l, tad)
+     {
+        evas_object_geometry_get(tad->obj, &tad->end.x, &tad->end.y,
+                                 &tad->end.w, &tad->end.h);
+        tad->end.x = tad->end.x - x;
+        tad->end.y = tad->end.y - y;
+     }
+}
+
+static Eina_Bool
+_transition_layout_load_children_list(Evas_Object_Box_Data *priv,
+                                      Elm_Box_Transition *layout_data)
+{
+   Eina_List *l;
+   Evas_Object_Box_Option *opt;
+   Transition_Animation_Data *tad;
+
+   EINA_LIST_FREE(layout_data->objs, tad)
+     free(tad);
+
+   EINA_LIST_FOREACH(priv->children, l, opt)
+     {
+        tad = calloc(1, sizeof(Transition_Animation_Data));
+        if (!tad)
+          {
+             EINA_LIST_FREE(layout_data->objs, tad)
+               free(tad);
+             layout_data->objs = NULL;
+             return EINA_FALSE;
+          }
+        tad->obj = opt->obj;
+        layout_data->objs = eina_list_append(layout_data->objs, tad);
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_transition_layout_animation_start(Evas_Object *obj, Evas_Object_Box_Data *priv,
+                                   Elm_Box_Transition *layout_data, Eina_Bool(*transition_animation_cb)(void *data))
+{
+   layout_data->start.layout(obj, priv, layout_data->start.data);
+   layout_data->box = obj;
+   layout_data->initial_time = ecore_loop_time_get();
+
+   if (!_transition_layout_load_children_list(priv, layout_data))
+      return EINA_FALSE;
+   _transition_layout_calculate_coords(obj, priv, layout_data);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, 
+                                  _transition_layout_obj_resize_cb, layout_data);
+   evas_object_smart_callback_add(obj, SIG_CHILD_ADDED, 
+                                  _transition_layout_child_added, layout_data);
+   evas_object_smart_callback_add(obj, SIG_CHILD_REMOVED, 
+                                  _transition_layout_child_removed, layout_data);
+   if (!layout_data->animator)
+      layout_data->animator = ecore_animator_add(transition_animation_cb, obj);
+   layout_data->animation_ended = EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static void
+_transition_layout_animation_stop(Elm_Box_Transition *layout_data)
+{
+   layout_data->animation_ended = EINA_TRUE;
+   if (layout_data->animator)
+     {
+        ecore_animator_del(layout_data->animator);
+        layout_data->animator = NULL;
+     }
+
+   if (layout_data->transition_end_cb)
+      layout_data->transition_end_cb(layout_data->transition_end_data);
+}
+
+static void
+_transition_layout_animation_exec(Evas_Object *obj, Evas_Object_Box_Data *priv __UNUSED__,
+                                  Elm_Box_Transition *layout_data, const double curtime)
+{
+   Eina_List *l;
+   Transition_Animation_Data *tad;
+   Evas_Coord x, y, w, h;
+   Evas_Coord cur_x, cur_y, cur_w, cur_h;
+   double progress = 0.0;
+
+   progress = (curtime - layout_data->initial_time) / layout_data->duration;
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+
+   EINA_LIST_FOREACH(layout_data->objs, l, tad)
+     {
+        cur_x = x + tad->start.x + ((tad->end.x - tad->start.x) * progress);
+        cur_y = y + tad->start.y + ((tad->end.y - tad->start.y) * progress);
+        cur_w = tad->start.w + ((tad->end.w - tad->start.w) * progress);
+        cur_h = tad->start.h + ((tad->end.h - tad->start.h) * progress);
+        evas_object_move(tad->obj, cur_x, cur_y);
+        evas_object_resize(tad->obj, cur_w, cur_h);
+     }
+}
+
+/**
+ * Add a new box to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Box
+ */
+EAPI Evas_Object *
+elm_box_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "box");
+   elm_widget_type_set(obj, "box");
+   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);
+   elm_widget_focus_next_hook_set(obj, _elm_box_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+   elm_widget_highlight_ignore_set(obj, EINA_TRUE);
+
+   wd->box = evas_object_box_add(e);
+   /*evas_object_box_layout_set(wd->box, evas_object_box_layout_vertical,
+                             NULL, NULL);*/
+   evas_object_box_layout_set(wd->box, _layout, wd, NULL);
+
+   evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                 _changed_size_hints, obj);
+   elm_widget_resize_object_set(obj, wd->box);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   return obj;
+}
+
+/**
+ * Set the horizontal orientation
+ *
+ * By default box object arrange their contents vertically from top to bottom.
+ * By calling this and providing @p horizontal as true, the box will become
+ * horizontal arranging contents left to right.
+ *
+ * @param obj The box object
+ * @param horizontal The horizontal flag (1 = horizontal, 0 = vertical)
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->horizontal = !!horizontal;
+   evas_object_smart_calculate(wd->box);
+   /*if (wd->horizontal)
+     {
+       if (wd->homogeneous)
+         evas_object_box_layout_set(wd->box,
+               evas_object_box_layout_homogeneous_horizontal, NULL, NULL);
+       else
+         evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
+                                    NULL, NULL);
+     }
+   else
+     {
+       if (wd->homogeneous)
+         evas_object_box_layout_set(wd->box,
+               evas_object_box_layout_homogeneous_vertical, NULL, NULL);
+       else
+         evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
+                                    NULL, NULL);
+     }*/
+}
+
+/**
+ * Get the horizontal orientation
+ *
+ * @param obj The box object
+ * @return If is horizontal
+ *
+ * @ingroup Box
+ */
+EAPI Eina_Bool
+elm_box_horizontal_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->horizontal;
+}
+
+/**
+ * Set homogenous layout
+ *
+ * If enabled, homogenous layout makes all items the same size. This size is
+ * of course governed by the size of the largest item in the box.
+ *
+ * @param obj The box object
+ * @param homogenous The homogenous flag (1 = on, 2 = off)
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->homogeneous = !!homogenous;
+   evas_object_smart_calculate(wd->box);
+   /*if (wd->horizontal)
+     {
+       if (wd->homogeneous)
+         evas_object_box_layout_set(wd->box,
+               evas_object_box_layout_homogeneous_horizontal, NULL, NULL);
+       else
+         evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
+                                    NULL, NULL);
+     }
+   else
+     {
+       if (wd->homogeneous)
+         evas_object_box_layout_set(wd->box,
+               evas_object_box_layout_homogeneous_vertical, NULL, NULL);
+       else
+         evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
+                                    NULL, NULL);
+     }*/
+}
+
+/**
+ * Get homogenous layout
+ *
+ * @param obj The box object
+ * @return If is homogenous
+ *
+ * @ingroup Box
+ */
+EAPI Eina_Bool
+elm_box_homogenous_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->homogeneous;
+}
+
+/**
+ * This adds a box at the start of the box (top or left based on orientation)
+ *
+ * This will add the @p subobj to the box object indicated at the beginning
+ * of the box (the left or top end).
+ *
+ * @param obj The box object
+ * @param subobj The object to add to the box
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_pack_start(Evas_Object *obj, Evas_Object *subobj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_sub_object_add(obj, subobj);
+   evas_object_box_prepend(wd->box, subobj);
+}
+
+/**
+ * This adds a box at the end of the box (bottom or right based on orientation)
+ *
+ * This will add the @p subobj to the box object indicated at the end
+ * of the box (the right or bottom end).
+ *
+ * @param obj The box object
+ * @param subobj The object to add to the box
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_pack_end(Evas_Object *obj, Evas_Object *subobj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_sub_object_add(obj, subobj);
+   evas_object_box_append(wd->box, subobj);
+}
+
+/**
+ * This adds adds an object to the box before the indicated object
+ *
+ * This will add the @p subobj to the box indicated before the object
+ * indicated with @p before. If @p before is not already in the box, results
+ * are undefined. Before means either to the left of the indicated object or
+ * above it depending on orientation.
+ *
+ * @param obj The box object
+ * @param subobj The object to add to the box
+ * @param before The object before which to add it
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_pack_before(Evas_Object *obj, Evas_Object *subobj, Evas_Object *before)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_sub_object_add(obj, subobj);
+   evas_object_box_insert_before(wd->box, subobj, before);
+}
+
+/**
+ * This adds adds an object to the box after the indicated object
+ *
+ * This will add the @p subobj to the box indicated after the object
+ * indicated with @p after. If @p after is not already in the box, results
+ * are undefined. After means either to the right of the indicated object or
+ * below it depending on orientation.
+ *
+ * @param obj The box object
+ * @param subobj The object to add to the box
+ * @param after The object after which to add it
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_pack_after(Evas_Object *obj, Evas_Object *subobj, Evas_Object *after)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_sub_object_add(obj, subobj);
+   evas_object_box_insert_after(wd->box, subobj, after);
+}
+
+/**
+ * This clears the box items
+ *
+ * This delete all members of the box object, but not the box itself.
+ *
+ * @param obj The box object
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_box_remove_all(wd->box, EINA_TRUE);
+}
+
+/**
+ * This unpack a box item
+ *
+ * This unpack the selected member from the box object, but does not delete
+ * the box itself or the packed items.
+ *
+ * @param obj The box object
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_unpack(Evas_Object *obj, Evas_Object *subobj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_box_remove(wd->box, subobj);
+}
+
+/**
+ * This unpack the box items
+ *
+ * This unpack all members from the box object, but does not delete
+ * the box itself or the packed items.
+ *
+ * @param obj The box object
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_unpack_all(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_box_remove_all(wd->box, EINA_FALSE);
+}
+
+/**
+ * Set the callback layout function (@p cb) to the @p obj elm_box class.
+ *
+ * This function will use evas_object_box_layout_set() to set @p cb as the
+ * layout callback function for this box object.
+ * All layout funtions from evas_object_box can be used as @p cb. Some examples
+ * are evas_object_box_layout_horizontal, evas_object_box_layout_vertical and
+ * evas_object_box_layout_stack. elm_box_layout_transition can also be used.
+ * If @p cb is NULL, the default layout function from elm_box will be used.
+ *
+ * @note Changing the layout function will make horizontal/homogeneous fields
+ * from Widget_Data have NO further usage as they are controlled by default
+ * layout function. So calling elm_box_horizontal_set() or
+ * elm_box_homogenous_set() won't affect layout behavior.
+ *
+ * @param obj The box object
+ * @param cb The callback function used for layout
+ * @param data Data that will be passed to layout function
+ * @param free_data Function called to free @p data
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_layout_set(Evas_Object *obj, Evas_Object_Box_Layout cb, const void *data, void (*free_data)(void *data))
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (cb)
+     evas_object_box_layout_set(wd->box, cb, data, free_data);
+   else
+     evas_object_box_layout_set(wd->box, _layout, wd, NULL);
+}
+
+/**
+ * Layout function which display a transition animation from start layout to end layout.
+ *
+ * This function should no be called directly. It may be used by elm_box_layout_set() or
+ * evas_object_box_layout_set() as a layout function.
+ * The @p data passed to this function must be a Elm_Box_Transition*, that can be created
+ * using elm_box_transition_new() and freed with elm_box_transition_free().
+ *
+ * Usage Example:
+ * @code
+ * Evas_Object *box = elm_box_add(parent);
+ * Elm_Box_Transition *t = elm_box_transition_new(...add params here...);
+ * elm_box_layout_set(box, elm_box_layout_transition, t, elm_box_transition_free);
+ * @endcode
+ *
+ * @see elm_box_transition_new
+ * @see elm_box_transition_free
+ * @see elm_box_layout_set
+ *
+ * @ingroup Box
+ * @warning Do not call this function directly because the @p obj is not the Widget Box
+ * from elm_box_add(), it is the internal Evas_Object of the Widget Box.
+ */
+EAPI void
+elm_box_layout_transition(Evas_Object *obj, Evas_Object_Box_Data *priv, void *data)
+{
+   Elm_Box_Transition *box_data = data;
+   const double curtime = ecore_loop_time_get();
+
+   if (box_data->animation_ended)
+     {
+          box_data->end.layout(obj, priv, box_data->end.data);
+          return;
+     }
+
+   if (!box_data->animator)
+     {
+        if (!_transition_layout_animation_start(obj, priv, box_data,
+            _transition_animation))
+           return;
+     }
+   else
+     {
+        if (box_data->recalculate)
+          {
+             _transition_layout_calculate_coords(obj, priv, box_data);
+             box_data->recalculate = EINA_FALSE;
+          }
+     }
+
+   if ((curtime >= box_data->duration + box_data->initial_time))
+      _transition_layout_animation_stop(box_data);
+   else
+      _transition_layout_animation_exec(obj, priv, box_data, curtime);
+}
+
+/**
+ * Create a new Elm_Box_Transition setted with informed parameters.
+ *
+ * The returned instance may be used as data parameter to elm_box_layout_transition()
+ * and should be freed with elm_box_transition_free().
+ *
+ * @param start_layout The layout function that will be used to start the animation
+ * @param start_layout_data The data to be passed the @p start_layout function
+ * @param start_layout_free_data Function to free @p start_layout_data
+ * @param end_layout The layout function that will be used to end the animation
+ * @param end_layout_free_data The data to be passed the @p end_layout function
+ * @param end_layout_free_data Function to free @p end_layout_data
+ * @param transition_end_cb Callback function called when animation ends
+ * @param transition_end_data Data to be passed to @p transition_end_cb
+ * @return An instance of Elm_Box_Transition setted with informed parameters
+ *
+ * @see elm_box_transition_new
+ * @see elm_box_layout_transition
+ *
+ * @ingroup Box
+ */
+EAPI Elm_Box_Transition *
+elm_box_transition_new(const double duration,
+      Evas_Object_Box_Layout start_layout, void *start_layout_data,
+      void(*start_layout_free_data)(void *data),
+      Evas_Object_Box_Layout end_layout, void *end_layout_data,
+      void(*end_layout_free_data)(void *data),
+      void(*transition_end_cb)(void *data),
+      void *transition_end_data)
+{
+   Elm_Box_Transition *box_data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(start_layout, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(end_layout, NULL);
+
+   box_data = calloc(1, sizeof(Elm_Box_Transition));
+   if (!box_data)
+      return NULL;
+
+   box_data->start.layout = start_layout;
+   box_data->start.data = start_layout_data;
+   box_data->start.free_data = start_layout_free_data;
+   box_data->end.layout = end_layout;
+   box_data->end.data = end_layout_data;
+   box_data->end.free_data = end_layout_free_data;
+   box_data->duration = duration;
+   box_data->transition_end_cb = transition_end_cb;
+   box_data->transition_end_data = transition_end_data;
+   return box_data;
+}
+
+/**
+ * Free a Elm_Box_Transition instance created with elm_box_transition_new().
+ *
+ * @param data The Elm_Box_Transition instance to be freed.
+ *
+ * @see elm_box_transition_new
+ * @see elm_box_layout_transition
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_transition_free(void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+
+   Transition_Animation_Data *tad;
+   Elm_Box_Transition *box_data = data;
+   if ((box_data->start.free_data) && (box_data->start.data))
+      box_data->start.free_data(box_data->start.data);
+   if ((box_data->end.free_data) && (box_data->end.data))
+      box_data->end.free_data(box_data->end.data);
+   EINA_LIST_FREE(box_data->objs, tad)
+      free(tad);
+   evas_object_event_callback_del(box_data->box, EVAS_CALLBACK_RESIZE, _transition_layout_obj_resize_cb);
+   evas_object_smart_callback_del(box_data->box, SIG_CHILD_ADDED, _transition_layout_child_added);
+   evas_object_smart_callback_del(box_data->box, SIG_CHILD_REMOVED, _transition_layout_child_removed);
+   if (box_data->animator)
+     {
+        ecore_animator_del(box_data->animator);
+        box_data->animator = NULL;
+     }
+   free(data);
+}
+
+/**
+ * Retrieve the list of children packed into an elm_box
+ *
+ * @param obj The Elm_Box
+ *
+ * @ingroup Box
+ */
+EAPI const Eina_List *
+elm_box_children_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return evas_object_box_children_get(wd->box);
+}
+
+/**
+ * Set the space (padding) between the box's elements.
+ *
+ * @param obj The Elm_Box
+ * @param horizontal The horizontal space between elements
+ * @param vertical The vertical space between elements
+ * 
+ * @ingroup Box
+ */
+EAPI void
+elm_box_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_box_padding_set(wd->box, horizontal, vertical);
+}
+
+/**
+ * Get the space (padding) between the box's elements.
+ *
+ * @param obj The Elm_Box
+ * @param horizontal The horizontal space between elements
+ * @param vertical The vertical space between elements
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_box_padding_get(wd->box, horizontal, vertical);
+}
+
+/**
+ * Set the alignment of the whole bouding box of contents.
+ *
+ * @param obj The Elm_Box
+ * @param horizontal The horizontal alignment of elements
+ * @param vertical The vertical alignment of elements
+ * 
+ * @ingroup Box
+ */
+EAPI void
+elm_box_align_set(Evas_Object *obj, double horizontal, double vertical)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_box_align_set(wd->box, horizontal, vertical);
+}
+
+/**
+ * Get the alignment of the whole bouding box of contents.
+ *
+ * @param obj The Elm_Box
+ * @param horizontal The horizontal alignment of elements
+ * @param vertical The vertical alignment of elements
+ *
+ * @ingroup Box
+ */
+EAPI void
+elm_box_align_get(const Evas_Object *obj, double *horizontal, double *vertical)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_box_align_get(wd->box, horizontal, vertical);
+}
diff --git a/src/lib/elm_bubble.c b/src/lib/elm_bubble.c
new file mode 100644 (file)
index 0000000..2be1dcd
--- /dev/null
@@ -0,0 +1,476 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Bubble Bubble
+ *
+ * The Bubble is an widget used to show a text in a frame as speech is
+ * represented in comics.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * clicked - This is called when a user has clicked the bubble.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *bbl;
+   Evas_Object *content, *icon;
+   const char *label, *info, *corner;
+};
+
+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);
+
+#define SIG_CLICKED "clicked"
+static const Evas_Smart_Cb_Description _signals[] =
+{
+  {SIG_CLICKED, ""},
+  {NULL, NULL}
+};
+
+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);
+   if (wd->info) eina_stringshare_del(wd->info);
+   if (wd->corner) eina_stringshare_del(wd->corner);
+   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->bbl, "bubble", wd->corner,
+                         elm_widget_style_get(obj));
+   edje_object_part_text_set(wd->bbl, "elm.text", wd->label);
+   if (wd->label) edje_object_signal_emit(wd->bbl, "elm,state,text,visible", "elm");
+   else edje_object_signal_emit(wd->bbl, "elm,state,text,hidden", "elm");
+   edje_object_part_text_set(wd->bbl, "elm.info", wd->info);
+   if (wd->info) edje_object_signal_emit(wd->bbl, "elm,state,info,visible", "elm");
+   else edje_object_signal_emit(wd->bbl, "elm,state,info,hidden", "elm");
+   if (wd->content)
+     {
+        edje_object_part_swallow(wd->bbl, "elm.swallow.content", wd->content);
+       edje_object_message_signal_process(wd->bbl);
+     }
+   if (wd->icon)
+     edje_object_signal_emit(wd->bbl, "elm,state,icon,visible", "elm");
+   else
+     edje_object_signal_emit(wd->bbl, "elm,state,icon,hidden", "elm");
+   edje_object_scale_set(wd->bbl,
+                         elm_widget_scale_get(obj) * _elm_config->scale);
+   _sizing_eval(obj);
+}
+
+static Eina_Bool
+_elm_bubble_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *cur;
+
+   if ((!wd) || (!wd->content))
+     return EINA_FALSE;
+
+   cur = wd->content;
+
+   /* Try Focus cycle in subitem */
+   return elm_widget_focus_next_get(cur, dir, next);
+}
+
+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->bbl, &minw, &minh, 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->content) wd->content = NULL;
+   else if (sub == wd->icon)
+     {
+       edje_object_signal_emit(wd->bbl, "elm,state,icon,hidden", "elm");
+       wd->icon = NULL;
+       edje_object_message_signal_process(wd->bbl);
+     }
+   _sizing_eval(obj);
+}
+
+static void
+_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Up *ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     return;
+   evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
+}
+
+/**
+ * Add a new bubble to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * This function adds a text bubble to the given parent evas object.
+ *
+ * @ingroup Bubble
+ */
+EAPI Evas_Object *
+elm_bubble_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "bubble");
+   elm_widget_type_set(obj, "bubble");
+   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_focus_next_hook_set(obj, _elm_bubble_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->corner = eina_stringshare_add("base");
+
+   wd->bbl = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->bbl, "bubble", "base", "default");
+   elm_widget_resize_object_set(obj, wd->bbl);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_event_callback_add(wd->bbl, EVAS_CALLBACK_MOUSE_UP,
+                                  _mouse_up, obj);
+
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the label of the bubble
+ *
+ * @param obj The bubble object
+ * @param label The string to set in the label
+ *
+ * This function sets the title of the bubble that is shown on top of
+ * the bubble.
+ *
+ * @ingroup Bubble
+ */
+EAPI void
+elm_bubble_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->bbl, "elm.text", label);
+   if (label) edje_object_signal_emit(wd->bbl, "elm,state,text,visible", "elm");
+   else edje_object_signal_emit(wd->bbl, "elm,state,text,hidden", "elm");
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the label of the bubble
+ *
+ * @param obj The bubble object
+ * @return The string of set in the label
+ *
+ * This function gets the title of the bubble that is shown on top of
+ * the bubble.
+ *
+ * @ingroup Bubble
+ */
+EAPI const char*
+elm_bubble_label_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->label;
+}
+
+/**
+ * Set the info of the bubble
+ *
+ * @param obj The bubble object
+ * @param info The given info about the bubble
+ *
+ * This function sets the text shown on the top right of bubble.
+ * In the Anchorblock example of the Elementary tests application it
+ * shows time.
+ *
+ * @ingroup Bubble
+ *
+ */
+EAPI void
+elm_bubble_info_set(Evas_Object *obj, const char *info)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->info, info);
+   edje_object_part_text_set(wd->bbl, "elm.info", info);
+   if (info) edje_object_signal_emit(wd->bbl, "elm,state,info,visible", "elm");
+   else edje_object_signal_emit(wd->bbl, "elm,state,info,hidden", "elm");
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the info of the bubble
+ *
+ * @param obj The bubble object
+ *
+ * @return The "info" string of the bubble
+ *
+ * This function gets the text set to be displayed at the top right of
+ * the bubble.
+ *
+ * @ingroup Bubble
+ *
+ */
+EAPI const char *
+elm_bubble_info_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->info;
+}
+
+/**
+ * Set the content to be shown in the bubble
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep the old content object, use the
+ * elm_bubble_content_unset() function.
+ *
+ * @param obj The bubble object
+ * @param content The given content of the bubble
+ *
+ * This function sets the content shown on the middle of the bubble.
+ * In the Anchorblock example of the Elementary tests application it
+ * shows time.
+ *
+ * @ingroup Bubble
+ */
+EAPI void
+elm_bubble_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content) evas_object_del(wd->content);
+   wd->content = content;
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+       evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->bbl, "elm.swallow.content", content);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the content shown in the bubble
+ *
+ * Return the content object which is set for this widget.
+ *
+ * @param obj The bubble object
+ * @return The content that is being used
+ *
+ * @ingroup Bubble
+ */
+EAPI Evas_Object *
+elm_bubble_content_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->content;
+}
+
+/**
+ * Unset the content shown in the bubble
+ *
+ * Unparent and return the content object which was set for this widget.
+ *
+ * @param obj The bubble object
+ * @return The content that was being used
+ *
+ * @ingroup Bubble
+ */
+EAPI Evas_Object *
+elm_bubble_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *content;
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   content = wd->content;
+   elm_widget_sub_object_del(obj, content);
+   edje_object_part_unswallow(wd->bbl, content);
+   wd->content = NULL;
+   return content;
+}
+
+/**
+ * Set the icon of the bubble
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * If you want to keep the old content object, use the
+ * elm_icon_content_unset() function.
+ *
+ * @param obj The bubble object
+ * @param icon The given icon for the bubble
+ *
+ * @ingroup Bubble
+ */
+EAPI void
+elm_bubble_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->bbl, "elm.swallow.icon", icon);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_signal_emit(wd->bbl, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->bbl);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the icon of the bubble
+ *
+ * @param obj The bubble object
+ * @return The icon for the bubble
+ *
+ * This function gets the icon shown on the top left of bubble.
+ *
+ * @ingroup Bubble
+ */
+EAPI Evas_Object *
+elm_bubble_icon_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->icon;
+}
+
+/**
+ * Unset the icon of the bubble
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The bubble object
+ * @return The icon that was being used
+ *
+ * @ingroup Bubble
+ */
+EAPI Evas_Object *
+elm_bubble_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *icon;
+   if (!wd) return NULL;
+   if (!wd->icon) return NULL;
+   icon = wd->icon;
+   elm_widget_sub_object_del(obj, icon);
+   edje_object_part_unswallow(wd->bbl, icon);
+   wd->icon = NULL;
+   return icon;
+}
+
+/**
+ * Set the corner of the bubble
+ *
+ * @param obj The bubble object.
+ * @param corner The given corner for the bubble.
+ *
+ * This function sets the corner of the bubble.
+ * The corner will be used to find the group in the theme
+ * For example, if you set the corner to "bottom_right",
+ * the following group will be searched:
+ * "elm/bubble/bottom_right/default",
+ * considering default style.
+ *
+ * @ingroup Bubble
+ */
+EAPI void
+elm_bubble_corner_set(Evas_Object *obj, const char *corner)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(corner);
+   eina_stringshare_replace(&wd->corner, corner);
+   _theme_hook(obj);
+}
+
+/**
+ * Get the corner of the bubble
+ *
+ * @param obj The bubble object.
+ * @return The given corner for the bubble.
+ *
+ * This function gets the corner of the bubble.
+ *
+ * @ingroup Bubble
+ */
+EAPI const char*
+elm_bubble_corner_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->corner;
+}
diff --git a/src/lib/elm_button.c b/src/lib/elm_button.c
new file mode 100644 (file)
index 0000000..6ebd759
--- /dev/null
@@ -0,0 +1,564 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Button Button
+ *
+ * This is a push-button. Press it and run some function. It can contain
+ * a simple label and icon object.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *btn, *icon;
+   const char *label;
+   Eina_Bool autorepeat;
+   Eina_Bool repeating;
+   double ar_threshold;
+   double ar_interval;
+   Ecore_Timer *timer;
+};
+
+static const char *widtype = NULL;
+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 _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 _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_pressed(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_unpressed(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _activate(Evas_Object *obj);
+static void _activate_hook(Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+
+static const char SIG_CLICKED[] = "clicked";
+static const char SIG_REPEATED[] = "repeated";
+static const char SIG_UNPRESSED[] = "unpressed";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CLICKED, ""},
+  {SIG_REPEATED, ""},
+  {SIG_UNPRESSED, ""},
+  {NULL, NULL}
+};
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+   if ((strcmp(ev->keyname, "Return")) &&
+       (strcmp(ev->keyname, "KP_Enter")) &&
+       (strcmp(ev->keyname, "space")))
+     return EINA_FALSE;
+   _activate(obj);
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   edje_object_signal_emit(wd->btn, "elm,anim,activate", "elm");
+   return EINA_TRUE;
+}
+
+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
+_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))
+     {
+       edje_object_signal_emit(wd->btn, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->btn, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->btn, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->btn, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *str;
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->btn, "button", "base", elm_widget_style_get(obj));
+   if (wd->icon)
+     edje_object_part_swallow(wd->btn, "elm.swallow.content", wd->icon);
+   if (wd->label)
+     edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
+   else
+     edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
+   if (wd->icon)
+     edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
+   else
+     edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
+   edje_object_part_text_set(wd->btn, "elm.text", wd->label);
+   if (elm_object_disabled_get(obj))
+     edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
+   edje_object_message_signal_process(wd->btn);
+   edje_object_scale_set(wd->btn, elm_widget_scale_get(obj) * _elm_config->scale);
+   str = edje_object_data_get(wd->btn, "focus_highlight");
+   if ((str) && (!strcmp(str, "on")))
+     elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
+   else
+     elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
+   _sizing_eval(obj);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (elm_widget_disabled_get(obj))
+     edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
+   else
+     edje_object_signal_emit(wd->btn, "elm,state,enabled", "elm");
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(wd->btn, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_add(wd->btn, emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(wd->btn, emission, source, func_cb,
+                                        data);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->btn, &minw, &minh, minw, minh);
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (obj != wd->icon) 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;
+   if (sub == wd->icon)
+     {
+       edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _changed_size_hints, obj);
+       wd->icon = NULL;
+       edje_object_message_signal_process(wd->btn);
+       _sizing_eval(obj);
+     }
+}
+
+static void
+_activate(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+   wd->repeating = EINA_FALSE;
+   evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
+}
+
+static void
+_activate_hook(Evas_Object *obj)
+{
+   _activate(obj);
+}
+
+static void
+_signal_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _activate(data);
+}
+
+static Eina_Bool
+_autorepeat_send(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+
+   evas_object_smart_callback_call(data, SIG_REPEATED, NULL);
+   if (!wd->repeating)
+     {
+       wd->timer = NULL;
+       return ECORE_CALLBACK_CANCEL;
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_autorepeat_initial_send(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+
+   if (wd->timer) ecore_timer_del(wd->timer);
+   wd->repeating = EINA_TRUE;
+   _autorepeat_send(data);
+   wd->timer = ecore_timer_add(wd->ar_interval, _autorepeat_send, data);
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_signal_pressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+
+   if ((wd->autorepeat) && (!wd->repeating))
+     {
+       if (wd->ar_threshold <= 0.0)
+         _autorepeat_initial_send(data); /* call immediately */
+       else
+         wd->timer = ecore_timer_add(wd->ar_threshold, _autorepeat_initial_send, data);
+     }
+}
+
+static void
+_signal_unpressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+   wd->repeating = EINA_FALSE;
+   evas_object_smart_callback_call(data, SIG_UNPRESSED, NULL);
+}
+
+/**
+ * Add a new button to the parent
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Button
+ */
+EAPI Evas_Object *
+elm_button_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "button");
+   elm_widget_type_set(obj, "button");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_activate_hook_set(obj, _activate_hook);
+   elm_widget_event_hook_set(obj, _event_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+
+   wd->btn = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->btn, "button", "base", "default");
+   edje_object_signal_callback_add(wd->btn, "elm,action,click", "",
+                                   _signal_clicked, obj);
+   edje_object_signal_callback_add(wd->btn, "elm,action,press", "",
+                                   _signal_pressed, obj);
+   edje_object_signal_callback_add(wd->btn, "elm,action,unpress", "",
+                                   _signal_unpressed, obj);
+   elm_widget_resize_object_set(obj, wd->btn);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _theme_hook(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the label used in the button
+ *
+ * @param obj The button object
+ * @param label The text will be written on the button
+ *
+ * @ingroup Button
+ */
+EAPI void
+elm_button_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);
+   if (label)
+     edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
+   else
+     edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
+   edje_object_message_signal_process(wd->btn);
+   edje_object_part_text_set(wd->btn, "elm.text", label);
+   _sizing_eval(obj);
+}
+
+EAPI const char *
+elm_button_label_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->label;
+}
+
+/**
+ * Set the icon used for the button
+ *
+ * Once the icon object is set, a previously set one will be deleted
+ * If you want to keep that old content object, use the
+ * elm_button_icon_unset() function.
+ *
+ * @param obj The button object
+ * @param icon The icon object for the button
+ *
+ * @ingroup Button
+ */
+EAPI void
+elm_button_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);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->btn, "elm.swallow.content", icon);
+       edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->btn);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the icon used for the button
+ *
+ * Return the icon object which is set for this widget.
+ *
+ * @param obj The button object
+ * @return The icon object that is being used
+ *
+ * @ingroup Button
+ */
+EAPI Evas_Object *
+elm_button_icon_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->icon;
+}
+
+/**
+ * Unset the icon used for the button
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The button object
+ * @return The icon object that was being used
+ *
+ * @ingroup Button
+ */
+EAPI Evas_Object *
+elm_button_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->icon) return NULL;
+   Evas_Object *icon = wd->icon;
+   elm_widget_sub_object_del(obj, wd->icon);
+   edje_object_part_unswallow(wd->btn, wd->icon);
+   wd->icon = NULL;
+   return icon;
+}
+
+/**
+ * Turn on/off the autorepeat event generated when the user keeps pressing on the button
+ *
+ * @param obj The button object
+ * @param on  A bool to turn on/off the event
+ *
+ * @ingroup Button
+ */
+EAPI void
+elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->timer)
+     {
+        ecore_timer_del(wd->timer);
+        wd->timer = NULL;
+     }
+   wd->autorepeat = on;
+   wd->repeating = EINA_FALSE;
+}
+
+/**
+ * Get if autorepeat event is on
+ *
+ * @param obj The button object
+ * @return If autorepeat is on
+ *
+ * @ingroup Button
+ */
+EAPI Eina_Bool
+elm_button_autorepeat_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->autorepeat;
+}
+
+/**
+ * Set the initial timeout before the autorepeat event is generated
+ *
+ * @param obj The button object
+ * @param t   Timeout
+ *
+ * @ingroup Button
+ */
+EAPI void
+elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->ar_threshold == t) return;
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+   wd->ar_threshold = t;
+}
+
+/**
+ * Get the initial timeout before the autorepeat event is generated
+ *
+ * @param obj The button object
+ * @return Timeout
+ *
+ * @ingroup Button
+ */
+EAPI double
+elm_button_autorepeat_initial_timeout_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->ar_threshold;
+}
+
+/**
+ * Set the interval between each generated autorepeat event
+ *
+ * @param obj The button object
+ * @param t   Interval
+ *
+ * @ingroup Button
+ */
+EAPI void
+elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->ar_interval == t) return;
+
+   wd->ar_interval = t;
+   if ((wd->repeating) && (wd->timer)) ecore_timer_interval_set(wd->timer, t);
+}
+
+/**
+ * Get the interval between each generated autorepeat event
+ *
+ * @param obj The button object
+ * @return Interval
+ *
+ * @ingroup Button
+ */
+EAPI double
+elm_button_autorepeat_gap_timeout_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->ar_interval;
+}
diff --git a/src/lib/elm_calendar.c b/src/lib/elm_calendar.c
new file mode 100644 (file)
index 0000000..3c2ff39
--- /dev/null
@@ -0,0 +1,1280 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Calendar
+ *
+ * A calendar is a widget that allows the user to select a date. It has
+ * support to adding check marks (holidays and checks by default). The calendar
+ * is displayed one month at a time.
+ *
+ * Weekday names and the function used to format month and year to
+ * be displayed can be set, giving more flexibility to this widget.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * changed - emitted when the user selects a day or changes the displayed
+ * month, what actually changes the selected day as well.
+ */
+
+typedef enum _Day_Color // EINA_DEPRECATED
+{
+  DAY_WEEKDAY = 0,
+  DAY_SATURDAY = 1,
+  DAY_SUNDAY = 2
+} Day_Color;
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *calendar;
+   Eina_List *marks;
+   double interval, first_interval;
+   int year_min, year_max, spin_speed;
+   int today_it, selected_it, first_day_it;
+   Ecore_Timer *spin, *update_timer;
+   char * (*format_func) (struct tm *stime);
+   const char *weekdays[7];
+   struct tm current_time, selected_time;
+   Day_Color day_color[42]; // EINA_DEPRECATED
+   Eina_Bool selection_enabled : 1;
+};
+
+struct _Elm_Calendar_Mark
+{
+   Evas_Object *obj;
+   Eina_List *node;
+   struct tm mark_time;
+   const char *mark_type;
+   Elm_Calendar_Mark_Repeat repeat;
+};
+
+static const char *widtype = NULL;
+static void _on_focus_hook(void *data, Evas_Object *obj);
+
+static const char *_days_abbrev[] =
+{
+   "Sun", "Mon", "Tue", "Wed",
+   "Thu", "Fri", "Sat"
+};
+
+static int _days_in_month[2][12] =
+{
+   {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+   {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+static Elm_Calendar_Mark *
+_mark_new(Evas_Object *obj, const char *mark_type, struct tm *mark_time, Elm_Calendar_Mark_Repeat repeat)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Calendar_Mark *mark;
+
+   if (!wd) return NULL;
+   mark = calloc(1, sizeof(Elm_Calendar_Mark));
+   if (!mark) return NULL;
+   mark->obj = obj;
+   mark->mark_type = eina_stringshare_add(mark_type);
+   mark->mark_time = *mark_time;
+   mark->repeat = repeat;
+   return mark;
+}
+
+static inline void
+_mark_free(Elm_Calendar_Mark *mark)
+{
+   eina_stringshare_del(mark->mark_type);
+   free(mark);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   if (!wd) return;
+   elm_coords_finger_size_adjust(8, &minw, 7, &minh);
+   edje_object_size_min_restricted_calc(wd->calendar, &minw, &minh, minw, minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static inline int
+_maxdays_get(struct tm *time)
+{
+   int month, year;
+
+   month = time->tm_mon;
+   year = time->tm_year + 1900;
+
+   return _days_in_month[((!(year % 4)) && 
+                          ((!(year % 400)) || 
+                              (year % 100)))]
+                        [month];
+}
+
+static inline void
+_unselect(Widget_Data *wd, int selected)
+{
+   char emission[32];
+   snprintf(emission, sizeof(emission), "cit_%i,unselected", selected);
+   edje_object_signal_emit(wd->calendar, emission, "elm");
+}
+
+static inline void
+_select(Widget_Data *wd, int selected)
+{
+   char emission[32];
+   snprintf(emission, sizeof(emission), "cit_%i,selected", selected);
+   edje_object_signal_emit(wd->calendar, emission, "elm");
+}
+
+static inline void
+_not_today(Widget_Data *wd)
+{
+   char emission[32];
+   snprintf(emission, sizeof(emission), "cit_%i,not_today", wd->today_it);
+   edje_object_signal_emit(wd->calendar, emission, "elm");
+   wd->today_it = -1;
+}
+
+static inline void
+_today(Widget_Data *wd, int it)
+{
+   char emission[32];
+   snprintf(emission, sizeof(emission), "cit_%i,today", it);
+   edje_object_signal_emit(wd->calendar, emission, "elm");
+   wd->today_it = it;
+}
+
+static char *
+_format_month_year(struct tm *stime)
+{
+   char buf[32];
+   if (!strftime(buf, sizeof(buf), "%B %Y", stime)) return NULL;
+   return strdup(buf);
+}
+
+static inline void
+_cit_mark(Evas_Object *cal, int cit, const char *mtype)
+{
+   char sign[64];
+   snprintf(sign, sizeof(sign), "cit_%i,%s", cit, mtype);
+   edje_object_signal_emit(cal, sign, "elm");
+}
+
+static inline int
+_weekday_get(int first_week_day, int day)
+{
+   return (day + first_week_day - 1) % 7;
+}
+
+// EINA_DEPRECATED
+static void
+_text_day_color_update(Widget_Data *wd, int pos)
+{
+   char emission[32];
+  
+   switch (wd->day_color[pos])
+    {
+    case DAY_WEEKDAY:
+      snprintf(emission, sizeof(emission), "cit_%i,weekday", pos);
+      break;
+    case DAY_SATURDAY:
+      snprintf(emission, sizeof(emission), "cit_%i,saturday", pos);
+      break;
+    case DAY_SUNDAY:
+      snprintf(emission, sizeof(emission), "cit_%i,sunday", pos);
+      break;
+    default:
+      return;
+    }
+  
+   edje_object_signal_emit(wd->calendar, emission, "elm");
+}
+
+// EINA_DEPRECATED
+static void
+_text_day_color_set(Widget_Data *wd, Day_Color col, int pos)
+{
+   if ((pos < 0) || (pos >= 42)) return;
+   if (wd->day_color[pos] == col) return;
+   wd->day_color[pos] = col;
+   _text_day_color_update(wd, pos);
+}
+
+static void
+_populate(Evas_Object *obj)
+{
+   int maxdays, day, mon, year, i;
+   Elm_Calendar_Mark *mark;
+   char part[12], day_s[3];
+   struct tm first_day;
+   Eina_List *l;
+   char *buf;
+   Eina_Bool last_row = EINA_TRUE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+
+   if (wd->today_it > 0) _not_today(wd);
+
+   maxdays = _maxdays_get(&wd->selected_time);
+   mon = wd->selected_time.tm_mon;
+   year = wd->selected_time.tm_year;
+
+   /* Set selected month */
+   buf = wd->format_func(&wd->selected_time);
+   if (buf)
+     {
+       edje_object_part_text_set(wd->calendar, "month_text", buf);
+       free(buf);
+     }
+   else
+     edje_object_part_text_set(wd->calendar, "month_text", "");
+
+   /* Set days */
+   day = 0;
+   first_day = wd->selected_time;
+   first_day.tm_mday = 1;
+   mktime(&first_day);
+
+   // Layout of the calendar is changed for removing the unfilled last row.
+   wd->first_day_it = first_day.tm_wday;
+  
+  if ((35 - wd->first_day_it) > (maxdays - 1)) last_row = EINA_FALSE;
+  
+  if (!last_row)
+    {
+      char emission[32];
+      
+      for (i = 0; i < 5; i++)
+        {
+          snprintf(emission, sizeof(emission), "cseph_%i,row_hide", i);
+          edje_object_signal_emit(wd->calendar, emission, "elm");
+        }
+      snprintf(emission, sizeof(emission), "cseph_%i,row_invisible", 5);
+      edje_object_signal_emit(wd->calendar, emission, "elm");
+      for (i = 0; i < 35; i++)
+        {
+          snprintf(emission, sizeof(emission), "cit_%i,cell_expanded", i);
+          edje_object_signal_emit(wd->calendar, emission, "elm");
+        }
+      for (i = 35; i < 42; i++)
+        {
+          snprintf(emission, sizeof(emission), "cit_%i,cell_invisible", i);
+          edje_object_signal_emit(wd->calendar, emission, "elm");
+        }
+    }
+  else
+    {
+      char emission[32];
+      
+      for (i = 0; i < 6; i++)
+        {
+          snprintf(emission, sizeof(emission), "cseph_%i,row_show", i);
+          edje_object_signal_emit(wd->calendar, emission, "elm");
+        }
+      for (i = 0; i < 42; i++)
+        {
+          snprintf(emission, sizeof(emission), "cit_%i,cell_default", i);
+          edje_object_signal_emit(wd->calendar, emission, "elm");
+        }
+    }
+  
+   for (i = 0; i < 42; i++)
+     {
+        _text_day_color_update(wd, i); // EINA_DEPRECATED
+       if ((!day) && (i == first_day.tm_wday)) day = 1;
+
+       if ((day == wd->current_time.tm_mday)
+             && (mon == wd->current_time.tm_mon)
+             && (year == wd->current_time.tm_year))
+         _today(wd, i);
+
+       if (day == wd->selected_time.tm_mday)
+         {
+            if ((wd->selected_it > -1) && (wd->selected_it != i))
+              _unselect(wd, wd->selected_it);
+
+            if (wd->selection_enabled) _select(wd, i);
+
+            wd->selected_it = i;
+         }
+
+       if ((day) && (day <= maxdays))
+         snprintf(day_s, sizeof(day_s), "%i", day++);
+       else
+          day_s[0] = 0;
+
+       snprintf(part, sizeof(part), "cit_%i.text", i);
+       edje_object_part_text_set(wd->calendar, part, day_s);
+       /* Clear previous marks */
+       _cit_mark(wd->calendar, i, "clear");
+     }
+
+   /* Set marks */
+   EINA_LIST_FOREACH(wd->marks, l, mark)
+     {
+       struct tm *mtime = &mark->mark_time;
+       int mon = wd->selected_time.tm_mon;
+       int year = wd->selected_time.tm_year;
+       int mday_it = mtime->tm_mday + wd->first_day_it - 1;
+
+       switch (mark->repeat)
+         {
+          case ELM_CALENDAR_UNIQUE:
+             if ((mtime->tm_mon == mon) && (mtime->tm_year == year))
+               _cit_mark(wd->calendar, mday_it, mark->mark_type);
+             break;
+          case ELM_CALENDAR_DAILY:
+             if (((mtime->tm_year == year) && (mtime->tm_mon < mon)) ||
+                   (mtime->tm_year < year))
+               day = 1;
+             else if ((mtime->tm_year == year) && (mtime->tm_mon == mon))
+               day = mtime->tm_mday;
+             else
+               break;
+             for (; day <= maxdays; day++)
+               _cit_mark(wd->calendar, day + wd->first_day_it - 1,
+                     mark->mark_type);
+             break;
+          case ELM_CALENDAR_WEEKLY:
+             if (((mtime->tm_year == year) && (mtime->tm_mon < mon)) ||
+                   (mtime->tm_year < year))
+               day = 1;
+             else if ((mtime->tm_year == year) && (mtime->tm_mon == mon))
+               day = mtime->tm_mday;
+             else
+               break;
+             for (; day <= maxdays; day++)
+               if (mtime->tm_wday == _weekday_get(wd->first_day_it, day))
+                 _cit_mark(wd->calendar, day + wd->first_day_it - 1,
+                       mark->mark_type);
+             break;
+          case ELM_CALENDAR_MONTHLY:
+             if (((mtime->tm_year < year) ||
+                      ((mtime->tm_year == year) && (mtime->tm_mon <= mon))) &&
+                   (mtime->tm_mday <= maxdays))
+               _cit_mark(wd->calendar, mday_it, mark->mark_type);
+             break;
+          case ELM_CALENDAR_ANNUALLY:
+             if ((mtime->tm_year <= year) && (mtime->tm_mon == mon) &&
+                   (mtime->tm_mday <= maxdays))
+               _cit_mark(wd->calendar, mday_it, mark->mark_type);
+             break;
+         }
+     }
+}
+
+static void
+_set_headers(Evas_Object *obj)
+{
+   static char part[] = "ch_0.text";
+   int i;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   for (i = 0; i < 7; i++)
+     {
+       part[3] = i + '0';
+       edje_object_part_text_set(wd->calendar, part, wd->weekdays[i]);
+     }
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   int i;
+   Elm_Calendar_Mark *mark;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+
+   if (wd->spin) ecore_timer_del(wd->spin);
+   if (wd->update_timer) ecore_timer_del(wd->update_timer);
+
+   if (wd->marks)
+     {
+       EINA_LIST_FREE(wd->marks, mark)
+         {
+           _mark_free(mark);
+         }
+     }
+
+   for (i = 0; i < 7; i++)
+     eina_stringshare_del(wd->weekdays[i]);
+
+   free(wd);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->calendar, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->calendar, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->calendar, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->calendar, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->calendar, "calendar", "base",
+                         elm_widget_style_get(obj));
+   _set_headers(obj);
+   _populate(obj);
+   edje_object_message_signal_process(wd->calendar);
+   edje_object_scale_set(wd->calendar,
+                         elm_widget_scale_get(obj) * _elm_config->scale);
+   _sizing_eval(obj);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(wd->calendar, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_add(wd->calendar, emission,
+                                   source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_del_full(wd->calendar, emission, source, func_cb,
+                                        data);
+}
+
+/* Set correct tm_wday and tm_yday after other fields changes*/
+static inline void
+_fix_selected_time(Widget_Data *wd)
+{
+   mktime(&wd->selected_time);
+}
+
+static Eina_Bool
+_update_month(Evas_Object *obj, int delta)
+{
+   struct tm time_check;
+   int maxdays;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+
+   /* check if it's a valid time. for 32 bits, year greater than 2037 is not */
+   time_check = wd->selected_time;
+   time_check.tm_mon += delta;
+   if (mktime(&time_check) == -1)
+     return EINA_FALSE;
+
+   wd->selected_time.tm_mon += delta;
+   if (wd->selected_time.tm_mon < 0)
+     {
+       if (wd->selected_time.tm_year == wd->year_min)
+         {
+            wd->selected_time.tm_mon++;
+            return EINA_FALSE;
+         }
+       wd->selected_time.tm_mon = 11;
+       wd->selected_time.tm_year--;
+     }
+   else if (wd->selected_time.tm_mon > 11)
+     {
+       if (wd->selected_time.tm_year == wd->year_max)
+         {
+            wd->selected_time.tm_mon--;
+            return EINA_FALSE;
+         }
+       wd->selected_time.tm_mon = 0;
+       wd->selected_time.tm_year++;
+     }
+
+   maxdays = _maxdays_get(&wd->selected_time);
+   if (wd->selected_time.tm_mday > maxdays)
+     wd->selected_time.tm_mday = maxdays;
+
+   _fix_selected_time(wd);
+   evas_object_smart_callback_call(obj, "changed", NULL);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_spin_value(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   if (_update_month(data, wd->spin_speed)) _populate(data);
+   wd->interval = wd->interval / 1.05;
+   ecore_timer_interval_set(wd->spin, wd->interval);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_button_inc_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->spin_speed = 1;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _spin_value, data);
+   _spin_value(data);
+}
+
+static void
+_button_dec_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->spin_speed = -1;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _spin_value, data);
+   _spin_value(data);
+}
+
+static void
+_button_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = NULL;
+}
+
+static int
+_get_item_day(Evas_Object *obj, int selected_it)
+{
+   int day;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+
+   day = selected_it - wd->first_day_it + 1;
+   if ((day < 0) || (day > _maxdays_get(&wd->selected_time)))
+     return 0;
+
+   return day;
+}
+
+static void
+_update_sel_it(Evas_Object *obj, int sel_it)
+{
+   int day;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->selection_enabled))
+      return;
+
+   day = _get_item_day(obj, sel_it);
+   if (!day)
+     return;
+
+   _unselect(wd, wd->selected_it);
+
+   wd->selected_it = sel_it;
+   wd->selected_time.tm_mday = day;
+   _select(wd, wd->selected_it);
+   _fix_selected_time(wd);
+   evas_object_smart_callback_call(obj, "changed", NULL);
+}
+
+static void
+_day_selected(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source)
+{
+   int sel_it;
+   Widget_Data *wd = elm_widget_data_get(data);
+   if ((!wd) || (!wd->selection_enabled))
+      return;
+   sel_it = atoi(source);
+
+   _update_sel_it(data, sel_it);
+}
+
+static inline int
+_time_to_next_day(struct tm *t)
+{
+  return ((((24 - t->tm_hour) * 60) - t->tm_min) * 60) - t->tm_sec;
+}
+
+static Eina_Bool
+_update_cur_date(void *data)
+{
+   time_t current_time;
+   int t, day;
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_RENEW;
+
+   if (wd->today_it > 0) _not_today(wd);
+
+   current_time = time(NULL);
+   localtime_r(&current_time, &wd->current_time);
+   t = _time_to_next_day(&wd->current_time);
+   ecore_timer_interval_set(wd->update_timer, t);
+
+   if ((wd->current_time.tm_mon != wd->selected_time.tm_mon) ||
+        (wd->current_time.tm_year!= wd->selected_time.tm_year))
+     return ECORE_CALLBACK_RENEW;
+
+   day = wd->current_time.tm_mday + wd->first_day_it - 1;
+   _today(wd, day);
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+   if (!wd->selection_enabled) return EINA_FALSE;
+
+   if ((!strcmp(ev->keyname, "Left")) ||
+       (!strcmp(ev->keyname, "KP_Left")))
+     {
+        _update_sel_it(obj, wd->selected_it-1);
+     }
+   else if ((!strcmp(ev->keyname, "Right")) ||
+            (!strcmp(ev->keyname, "KP_Right")))
+     {
+        _update_sel_it(obj, wd->selected_it+1);
+     }
+   else if ((!strcmp(ev->keyname, "Up"))  ||
+            (!strcmp(ev->keyname, "KP_Up")))
+     {
+        _update_sel_it(obj, wd->selected_it-7);
+     }
+   else if ((!strcmp(ev->keyname, "Down")) ||
+            (!strcmp(ev->keyname, "KP_Down")))
+     {
+        _update_sel_it(obj, wd->selected_it+7);
+     }
+   else if ((!strcmp(ev->keyname, "Prior")) ||
+            (!strcmp(ev->keyname, "KP_Prior")))
+     {
+        if (_update_month(obj, -1)) _populate(obj);
+     }
+   else if ((!strcmp(ev->keyname, "Next")) ||
+            (!strcmp(ev->keyname, "KP_Next")))
+     {
+        if (_update_month(obj, 1)) _populate(obj);
+     }
+   else return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+/**
+ * Add a new calendar to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Calendar
+ */
+EAPI Evas_Object *
+elm_calendar_add(Evas_Object *parent)
+{
+   time_t current_time;
+   Evas_Object *obj;
+   Widget_Data *wd;
+   int i, t;
+   Evas *e;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "calendar");
+   elm_widget_type_set(obj, "calendar");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->first_interval = 0.85;
+   wd->year_min = 2;
+   wd->year_max = -1;
+   wd->today_it = -1;
+   wd->selected_it = -1;
+   wd->first_day_it = -1;
+   wd->selection_enabled = EINA_TRUE;
+   wd->format_func = _format_month_year;
+   wd->marks = NULL;
+
+   wd->calendar = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->calendar, "calendar", "base", "default");
+   elm_widget_resize_object_set(obj, wd->calendar);
+
+   edje_object_signal_callback_add(wd->calendar, "elm,action,increment,start",
+                                   "*", _button_inc_start, obj);
+   edje_object_signal_callback_add(wd->calendar, "elm,action,decrement,start",
+                                   "*", _button_dec_start, obj);
+   edje_object_signal_callback_add(wd->calendar, "elm,action,stop",
+                                   "*", _button_stop, obj);
+   edje_object_signal_callback_add(wd->calendar, "elm,action,selected",
+                                   "*", _day_selected, obj);
+
+   for (i = 0; i < 7; i++)
+     wd->weekdays[i] = eina_stringshare_add(_days_abbrev[i]);
+
+   current_time = time(NULL);
+   localtime_r(&current_time, &wd->selected_time);
+   wd->current_time = wd->selected_time;
+   t = _time_to_next_day(&wd->current_time);
+   wd->update_timer = ecore_timer_add(t, _update_cur_date, obj);
+
+   _set_headers(obj);
+   _populate(obj);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set weekdays names to display in the calendar.
+ *
+ * By default, the following abbreviations are displayed:
+ * "Sun, Mon, Tue, Wed, Thu, Fri, Sat"
+ * The first string should be related to Sunday, the second to Monday...
+ *
+ * The usage should be like this:
+ * @code
+ *   const char *weekdays[] =
+ *   {
+ *      "Sunday", "Monday", "Tuesday", "Wednesday",
+ *      "Thursday", "Friday", "Saturday"
+ *   };
+ *   elm_calendar_weekdays_names_set(calendar, weekdays);
+ * @endcode
+ *
+ * @param obj The calendar object
+ * @param weedays Array of seven strings to be used as weekday names.
+ * Warning: it must have 7 elements, or it will access invalid memory.
+ * The strings must be NULL terminated ('@\0').
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_weekdays_names_set(Evas_Object *obj, const char *weekdays[])
+{
+   int i;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   EINA_SAFETY_ON_NULL_RETURN(weekdays);
+
+   for (i = 0; i < 7; i++)
+     {
+        eina_stringshare_replace(&wd->weekdays[i], weekdays[i]);
+     }
+   _set_headers(obj);
+}
+
+/**
+ * Get weekdays names displayed in the calendar.
+ *
+ * By default, the following abbreviations are displayed:
+ * "Sun, Mon, Tue, Wed, Thu, Fri, Sat"
+ * The first string is related to Sunday, the second to Monday...
+ *
+ * @param obj The calendar object
+ * @return Array of seven strings to used as weekday names.
+ *
+ * @ingroup Calendar
+ */
+EAPI const char **
+elm_calendar_weekdays_names_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->weekdays;
+}
+
+/**
+ * Set the interval for the calendar
+ *
+ * The interval value is decreased while the user increments or decrements
+ * the calendar value. The next interval value is the previous interval / 1.05,
+ * so it speed up a bit. Default value is 0.85 seconds.
+ *
+ * @param obj The calendar object
+ * @param interval The interval value in seconds
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_interval_set(Evas_Object *obj, double interval)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->first_interval = interval;
+}
+
+/**
+ * Get the interval of the calendar
+ *
+ * The interval value is decreased while the user increments or decrements
+ * the calendar value. The next interval value is the previous interval / 1.05,
+ * so it speed up a bit. Default value is 0.85 seconds.
+ *
+ * @param obj The calendar object
+ * @return The value of the first interval in seconds
+ *
+ * @ingroup Calendar
+ */
+EAPI double
+elm_calendar_interval_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->first_interval;
+}
+
+/**
+ * Set the minimum and maximum values for the year
+ *
+ * Maximum must be greater than minimum, except if you don't wan't to set
+ * maximum year.
+ * Default values are 1902 and -1.
+ *
+ * If the maximum year is a negative value, it will be limited depending of the
+ * platform architecture (2037 for 32 bits);
+ *
+ * @param obj The calendar object
+ * @param min The minimum year, greater than 1901;
+ * @param max The maximum year;
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_min_max_year_set(Evas_Object *obj, int min, int max)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   min -= 1900;
+   max -= 1900;
+   if ((wd->year_min == min) && (wd->year_max == max)) return;
+   wd->year_min = min > 2 ? min : 2;
+   wd->year_max = max;
+   if (wd->selected_time.tm_year > wd->year_max)
+     wd->selected_time.tm_year = wd->year_max;
+   if (wd->selected_time.tm_year < wd->year_min)
+     wd->selected_time.tm_year = wd->year_min;
+   _fix_selected_time(wd);
+   _populate(obj);
+}
+
+/**
+ * Get the minimum and maximum values for the year
+ *
+ * Default values are 1902 and -1.
+ *
+ * If the maximum year is a negative value, it will be limited depending of the
+ * platform architecture (2037 for 32 bits);
+ *
+ * @param obj The calendar object
+ * @param min The minimum year
+ * @param max The maximum year
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_min_max_year_get(const Evas_Object *obj, int *min, int *max)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (min) *min = wd->year_min + 1900;
+   if (max) *max = wd->year_max + 1900;
+}
+
+/**
+ * Enable or disable day selection
+ *
+ * Enabled by default. If disabled, the user can select months, but not days.
+ * It should be used if you won't need such selection for the widget usage.
+ *
+ * @param obj The calendar object
+ * @param enabled Boolean to enable (true) or disable (false) day selection
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_day_selection_enabled_set(Evas_Object *obj, Eina_Bool enabled)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->selection_enabled = enabled;
+   if (enabled)
+     _select(wd, wd->selected_it);
+   else
+     _unselect(wd, wd->selected_it);
+}
+
+/**
+ * Get day selection state
+ *
+ * Enabled by default. If disabled, the user can select months, but not days.
+ * It should be used if you won't need such selection for the widget usage.
+ *
+ * @param obj The calendar object
+ * @return True if day selection is enabled, or false otherwise. It will
+ * return false if it can't get widget data.
+ *
+ * @ingroup Calendar
+ */
+EAPI Eina_Bool
+elm_calendar_day_selection_enabled_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->selection_enabled;
+}
+
+/**
+ * Set selected time
+ *
+ * Set the time selected, changing the displayed month if needed.
+ * Selected time changes when the user changes the month or select a day.
+ *
+ * @param obj The calendar object
+ * @param selected_time A tm struct to represent the selected date
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_selected_time_set(Evas_Object *obj, struct tm *selected_time)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   EINA_SAFETY_ON_NULL_RETURN(selected_time);
+   wd->selected_time = *selected_time;
+   _populate(obj);
+   return;
+}
+
+/**
+ * Get selected time
+ *
+ * Get the time selected by the user.
+ * Selected time changes when the user changes the month or select a day.
+ *
+ * @param obj The calendar object
+ * @param selected_time A tm struct to represent the selected date
+ * @return It will return false if it can't get widget data, or true otherwise
+ *
+ * @ingroup Calendar
+ */
+EAPI Eina_Bool
+elm_calendar_selected_time_get(const Evas_Object *obj, struct tm *selected_time)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(selected_time, EINA_FALSE);
+   *selected_time = wd->selected_time;
+   return EINA_TRUE;
+}
+
+/**
+ * Set a function to format the string that will be used to display
+ * month - year
+ *
+ * By default it uses strftime with "%B %Y" format string.
+ * It should allocate the memory that will be used by the string,
+ * that will be freed by the widget after usage.
+ * A pointer to the string and a pointer to the time struct will be provided.
+ *
+ * Example:
+ * @code
+ * static char *
+ * _format_month_year(struct tm *stime)
+ * {
+ *    char buf[32];
+ *    if (!strftime(buf, sizeof(buf), "%B %Y", stime)) return NULL;
+ *    return strdup(buf);
+ * }
+ * elm_calendar_format_function_set(calendar, _format_month_year);
+ * @endcode
+ *
+ * @param obj The calendar object
+ * @param format_function Function to set the month-year string given
+ * the selected date
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_format_function_set(Evas_Object *obj, char * (*format_function) (struct tm *stime))
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->format_func = format_function;
+}
+
+/**
+ * Add a new mark to the calendar
+ *
+ * Add a mark that will be drawn in the calendar respecting the insertion time
+ * and periodicity. It will emit the type as signal to the widget theme.
+ * By default, it supports "holiday" and "checked", but it can be extended.
+ *
+ * It won't immediately update the calendar, drawing the marks. For this, call
+ * elm_calendar_marks_draw().
+ *
+ * Example
+ * @code
+ * struct tm selected_time;
+ * time_t current_time;
+ *
+ * current_time = time(NULL) + 5 * 84600;
+ * localtime_r(&current_time, &selected_time);
+ * elm_calendar_mark_add(cal, "holiday", selected_time, ELM_CALENDAR_ANNUALLY);
+ *
+ * current_time = time(NULL) + 1 * 84600;
+ * localtime_r(&current_time, &selected_time);
+ * elm_calendar_mark_add(cal, "checked", selected_time, ELM_CALENDAR_UNIQUE);
+ *
+ * elm_calendar_marks_draw(cal);
+ * @endcode
+ *
+ * @param obj The calendar object
+ * @param mark_type A string used to define the type of mark. It will be
+ * emitted to the theme, that should display a related modification on these
+ * days representation.
+ * @param mark_time A time struct to represent the date of inclusion of the
+ * mark. For marks that repeats it will just be displayed after the inclusion
+ * date in the calendar.
+ * @param repeat Repeat the event following this periodicity. Can be a unique
+ * mark (that don't repeat), daily, weekly, monthly or annually.
+ *
+ * @return The created mark or NULL upon failure
+ *
+ * @ingroup Calendar
+ */
+EAPI Elm_Calendar_Mark *
+elm_calendar_mark_add(Evas_Object *obj, const char *mark_type, struct tm *mark_time, Elm_Calendar_Mark_Repeat repeat)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Calendar_Mark *mark;
+   if (!wd) return NULL;
+
+   mark = _mark_new(obj, mark_type, mark_time, repeat);
+   wd->marks = eina_list_append(wd->marks, mark);
+   mark->node = eina_list_last(wd->marks);
+   return mark;
+}
+
+/**
+ * Delete mark from the calendar.
+ *
+ * @param mark The mark to delete
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_mark_del(Elm_Calendar_Mark *mark)
+{
+   Evas_Object *obj;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN(mark);
+
+   obj = mark->obj;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   wd->marks = eina_list_remove_list(wd->marks, mark->node);
+   _mark_free(mark);
+}
+
+/**
+ * Remove all the marks from the calendar
+ *
+ * @param obj The calendar object
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_marks_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Calendar_Mark *mark;
+
+   if (!wd) return;
+   EINA_LIST_FREE(wd->marks, mark)
+      _mark_free(mark);
+}
+
+/**
+ * Returns a list of all the calendar marks.
+ *
+ * @param obj The calendar object
+ * @return An Eina_List* of the calendar marks, or NULL on failure
+ *
+ * @ingroup Calendar
+ */
+EAPI const Eina_List *
+elm_calendar_marks_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->marks;
+}
+
+/**
+ * Draw calendar marks.
+ *
+ * Should be used after adding, removing or clearing marks.
+ * It will go through the entire marks list updating the calendar
+ * (not a cheap function). So if lots of marks will be added,
+ * add all the marks and then call this function.
+ *
+ * When the month is changed marks will be drawed.
+ *
+ * @param obj The calendar object
+ *
+ * @ingroup Calendar
+ */
+EAPI void
+elm_calendar_marks_draw(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _populate(obj);
+}
+
+/**
+ * Set a text color to the saturday color.
+ * 
+ * Deprecated. use elm_calendar_mark_add() instead like:
+ * 
+ * @code
+ * struct tm t = { 0, 0, 12, 6, 0, 0, 5, 5, -1 };
+ * elm_calendar_mark_add(obj, "sat", &t, ELM_CALENDAR_WEEKLY);
+ * @endcode
+ * 
+ * @param obj The calendar object
+ * @param pos The text position
+ *
+ * @ingroup Calendar
+ */
+EINA_DEPRECATED EAPI void
+elm_calendar_text_saturday_color_set(Evas_Object *obj, int pos)
+{
+  ELM_CHECK_WIDTYPE(obj, widtype);
+  Widget_Data *wd = elm_widget_data_get(obj);
+  if (!wd) return;
+  _text_day_color_set(wd, DAY_SATURDAY, pos);
+}
+
+/**
+ * Set a text color to the sunday color.
+ *
+ * Deprecated. use elm_calendar_mark_add() instead like:
+ * 
+ * @code
+ * struct tm t = { 0, 0, 12, 7, 0, 0, 6, 6, -1 };
+ * elm_calendar_mark_add(obj, "sun", &t, ELM_CALENDAR_WEEKLY);
+ * @endcode
+ * 
+ * @param obj The calendar object
+ * @param pos The text position
+ *
+ * @ingroup Calendar
+ */
+EINA_DEPRECATED EAPI void
+elm_calendar_text_sunday_color_set(Evas_Object *obj, int pos)
+{
+  ELM_CHECK_WIDTYPE(obj, widtype);
+  Widget_Data *wd = elm_widget_data_get(obj);
+  if (!wd) return;
+  _text_day_color_set(wd, DAY_SUNDAY, pos);
+}
+
+/**
+ * Set a text color to the weekday color.
+ *
+ * Deprecated. use elm_calendar_mark_add() instead like:
+ * 
+ * @code
+ * struct tm t = { 0, 0, 12, 1, 0, 0, 0, 0, -1 };
+ * 
+ * elm_calendar_mark_add(obj, "week", &t, ELM_CALENDAR_WEEKLY); // monday
+ * t.tm_tm_mday++; t.tm_wday++; t.tm_yday++;
+ * elm_calendar_mark_add(obj, "week", &t, ELM_CALENDAR_WEEKLY); // tuesday
+ * t.tm_tm_mday++; t.tm_wday++; t.tm_yday++;
+ * elm_calendar_mark_add(obj, "week", &t, ELM_CALENDAR_WEEKLY); // wednesday
+ * t.tm_tm_mday++; t.tm_wday++; t.tm_yday++;
+ * elm_calendar_mark_add(obj, "week", &t, ELM_CALENDAR_WEEKLY); // thursday
+ * t.tm_tm_mday++; t.tm_wday++; t.tm_yday++;
+ * elm_calendar_mark_add(obj, "week", &t, ELM_CALENDAR_WEEKLY); // friday
+ * @endcode
+ * 
+ * @param obj The calendar object
+ * @param pos The text position
+ *
+ * @ingroup Calendar
+ */
+EINA_DEPRECATED EAPI void
+elm_calendar_text_weekday_color_set(Evas_Object *obj, int pos)
+{
+  ELM_CHECK_WIDTYPE(obj, widtype);
+  Widget_Data *wd = elm_widget_data_get(obj);
+  if (!wd) return;
+  _text_day_color_set(wd, DAY_WEEKDAY, pos);
+}
diff --git a/src/lib/elm_check.c b/src/lib/elm_check.c
new file mode 100644 (file)
index 0000000..00badfa
--- /dev/null
@@ -0,0 +1,471 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Check Check
+ *
+ * The check widget allows for toggling a value between true or false (1 or 0).
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * changed - This is called whenever the user changes the state of one of the
+ * check object.
+ *
+ * Check objects are a lot like radio objects in layout and functionality
+ * except they do not work as a group, but independently and only toggle the
+ * value of a boolean from false to true (0 or 1). elm_check_state_set() sets
+ * the boolean state (1 for true, 0 for false), and elm_check_state_get()
+ * returns the current state. For convenience, like the radio objects, you
+ * can set a pointer to a boolean directly with elm_check_state_pointer_set()
+ * for it to modify.
+ */
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *chk, *icon;
+   Eina_Bool state;
+   Eina_Bool *statep;
+   const char *label;
+};
+
+static const char *widtype = NULL;
+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 _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 _signal_check_off(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_check_on(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_check_toggle(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _activate_hook(Evas_Object *obj);
+static void _activate(Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+
+static const char SIG_CHANGED[] = "changed";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CHANGED, ""},
+  {NULL, NULL}
+};
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+   if ((strcmp(ev->keyname, "Return")) &&
+       (strcmp(ev->keyname, "KP_Enter")) &&
+       (strcmp(ev->keyname, "space")))
+     return EINA_FALSE;
+   _activate(obj);
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+}
+
+
+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
+_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))
+     {
+       edje_object_signal_emit(wd->chk, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->chk, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->chk, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->chk, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->chk, "check", "base", elm_widget_style_get(obj));
+   if (wd->icon)
+      edje_object_signal_emit(wd->chk, "elm,state,icon,visible", "elm");
+   else
+      edje_object_signal_emit(wd->chk, "elm,state,icon,hidden", "elm");
+   if (wd->state)
+      edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
+   else
+      edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
+   if (wd->label)
+      edje_object_signal_emit(wd->chk, "elm,state,text,visible", "elm");
+   else
+      edje_object_signal_emit(wd->chk, "elm,state,text,hidden", "elm");
+   edje_object_part_text_set(wd->chk, "elm.text", wd->label);
+   if (elm_widget_disabled_get(obj))
+      edje_object_signal_emit(wd->chk, "elm,state,disabled", "elm");
+   edje_object_message_signal_process(wd->chk);
+   edje_object_scale_set(wd->chk, 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) return;
+   if (elm_widget_disabled_get(obj))
+      edje_object_signal_emit(wd->chk, "elm,state,disabled", "elm");
+   else
+      edje_object_signal_emit(wd->chk, "elm,state,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;
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->chk, &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_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (obj != wd->icon) return;
+   Evas_Coord mw, mh;
+   evas_object_size_hint_min_get(obj, &mw, &mh);
+   _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;
+   if (sub == wd->icon)
+     {
+       edje_object_signal_emit(wd->chk, "elm,state,icon,hidden", "elm");
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _changed_size_hints, obj);
+       wd->icon = NULL;
+       _sizing_eval(obj);
+       edje_object_message_signal_process(wd->chk);
+     }
+}
+
+static void
+_signal_check_off(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->state = EINA_FALSE;
+   if (wd->statep) *wd->statep = wd->state;
+   edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
+   evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
+}
+
+static void
+_signal_check_on(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->state = EINA_TRUE;
+   if (wd->statep) *wd->statep = wd->state;
+   edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
+   evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
+}
+
+static void
+_signal_check_toggle(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _activate(data);
+}
+
+static void
+_activate_hook(Evas_Object *obj)
+{
+   _activate(obj);
+}
+
+static void
+_activate(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->state = !wd->state;
+   if (wd->statep) *wd->statep = wd->state;
+   if (wd->state)
+     edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
+   else
+     edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
+   evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
+}
+
+/**
+ * Add a new Check object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Check
+ */
+EAPI Evas_Object *
+elm_check_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "check");
+   elm_widget_type_set(obj, "check");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_activate_hook_set(obj, _activate_hook);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->chk = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->chk, "check", "base", "default");
+   edje_object_signal_callback_add(wd->chk, "elm,action,check,on", "",
+                                   _signal_check_on, obj);
+   edje_object_signal_callback_add(wd->chk, "elm,action,check,off", "",
+                                   _signal_check_off, obj);
+   edje_object_signal_callback_add(wd->chk, "elm,action,check,toggle", "",
+                                   _signal_check_toggle, obj);
+   elm_widget_resize_object_set(obj, wd->chk);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the text label of the check object
+ *
+ * @param obj The check object
+ * @param label The text label string in UTF-8
+ *
+ * @ingroup Check
+ */
+EAPI void
+elm_check_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);
+   if (label)
+     edje_object_signal_emit(wd->chk, "elm,state,text,visible", "elm");
+   else
+     edje_object_signal_emit(wd->chk, "elm,state,text,hidden", "elm");
+   edje_object_message_signal_process(wd->chk);
+   edje_object_part_text_set(wd->chk, "elm.text", label);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the text label of the check object
+ *
+ * @param obj The check object
+ * @return The text label string in UTF-8
+ *
+ * @ingroup Check
+ */
+EAPI const char *
+elm_check_label_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->label;
+}
+
+/**
+ * Set the icon object of the check object
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_check_icon_unset() function.
+ *
+ * @param obj The check object
+ * @param icon The icon object
+ *
+ * @ingroup Check
+ */
+EAPI void
+elm_check_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);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->chk, "elm.swallow.content", icon);
+       edje_object_signal_emit(wd->chk, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->chk);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the icon object of the check object
+ *
+ * @param obj The check object
+ * @return The icon object
+ *
+ * @ingroup Check
+ */
+EAPI Evas_Object *
+elm_check_icon_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->icon;
+}
+
+/**
+ * Unset the icon used for the check object
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The check object
+ * @return The icon object that was being used
+ *
+ * @ingroup Check
+ */
+EAPI Evas_Object *
+elm_check_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->icon) return NULL;
+   Evas_Object *icon = wd->icon;
+   elm_widget_sub_object_del(obj, wd->icon);
+   edje_object_part_unswallow(wd->chk, wd->icon);
+   wd->icon = NULL;
+   return icon;
+}
+
+/**
+ * Set the on/off state of the check object
+ *
+ * This sets the state of the check and will also set the value if pointed to
+ * to the state supplied, but will not call any callbacks.
+ *
+ * @param obj The check object
+ * @param state The state to use (1 == on, 0 == off)
+ *
+ * @ingroup Check
+ */
+EAPI void
+elm_check_state_set(Evas_Object *obj, Eina_Bool state)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (state != wd->state)
+     {
+       wd->state = state;
+       if (wd->statep) *wd->statep = wd->state;
+       if (wd->state)
+         edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
+       else
+         edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
+     }
+}
+
+/**
+ * Get the state of the check object
+ *
+ * @param obj The check object
+ * @return The boolean state
+ *
+ * @ingroup Check
+ */
+EAPI Eina_Bool
+elm_check_state_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->state;
+}
+
+/**
+ * Set a convenience pointer to a boolean to change
+ *
+ * This sets a pointer to a boolean, that, in addition to the check objects
+ * state will also be modified directly. To stop setting the object pointed
+ * to simply use NULL as the statep parameter. If statep is not NULL, then
+ * when this is called, the check objects state will also be modified to
+ * reflect the value of the boolean statep points to, just like calling
+ * elm_check_state_set().
+ *
+ * @param obj The check object
+ * @param statep Pointer to the boolean to modify
+ *
+ * @ingroup Check
+ */
+EAPI void
+elm_check_state_pointer_set(Evas_Object *obj, Eina_Bool *statep)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (statep)
+     {
+       wd->statep = statep;
+       if (*wd->statep != wd->state)
+         {
+            wd->state = *wd->statep;
+            if (wd->state)
+              edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
+            else
+              edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
+         }
+     }
+   else
+     wd->statep = NULL;
+}
diff --git a/src/lib/elm_clock.c b/src/lib/elm_clock.c
new file mode 100644 (file)
index 0000000..f00dfea
--- /dev/null
@@ -0,0 +1,837 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Clock Clock
+ *
+ * It's a widget to show clock with animation. The update of time is
+ * shown in an animation like the flip of a sheet.
+ *
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *clk;
+   double interval, first_interval;
+   Eina_Bool seconds : 1;
+   Eina_Bool am_pm : 1;
+   Eina_Bool edit : 1;
+   Elm_Clock_Digedit digedit;
+   int hrs, min, sec, timediff;
+   Evas_Object *digit[6];
+   Evas_Object *ampm;
+   Evas_Object *sel_obj;
+   Ecore_Timer *ticker, *spin;
+   struct
+     {
+        int hrs, min, sec;
+        char ampm;
+        Eina_Bool seconds : 1;
+        Eina_Bool am_pm : 1;
+        Eina_Bool edit : 1;
+       Elm_Clock_Digedit digedit;
+     } cur;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static Eina_Bool _ticker(void *data);
+static Eina_Bool _signal_clock_val_up(void *data);
+static Eina_Bool _signal_clock_val_down(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;
+   int i;
+   for (i = 0; i < 6; i++)
+     {
+       if (wd->digit[i]) evas_object_del(wd->digit[i]);
+     }
+   if (wd->ampm) evas_object_del(wd->ampm);
+   if (wd->ticker) ecore_timer_del(wd->ticker);
+   if (wd->spin) ecore_timer_del(wd->spin);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (elm_widget_focus_get(obj))
+     edje_object_signal_emit(wd->clk, "elm,action,focus", "elm");
+   else
+     edje_object_signal_emit(wd->clk, "elm,action,unfocus", "elm");
+   wd->cur.am_pm = !wd->cur.am_pm; /* hack - force update */
+   _time_update(obj);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->clk, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->clk, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->clk, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->clk, EINA_FALSE);
+     }
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int i;
+   if (!wd) return;
+   edje_object_signal_emit(wd->clk, emission, source);
+   for (i = 0; i < 6; i++)
+     {
+       if (wd->digit[i])
+         edje_object_signal_emit(wd->digit[i], emission, source);
+     }
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int i;
+   if (!wd) return;
+   edje_object_signal_callback_add(wd->clk, emission, source, func_cb, data);
+   for (i = 0; i < 6; i++)
+     {
+       if (wd->digit[i])
+         edje_object_signal_callback_add(wd->digit[i], emission, source,
+               func_cb, data);
+     }
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int i;
+   for (i = 0; i < 6; i++)
+     {
+       edje_object_signal_callback_del_full(wd->digit[i], emission, source,
+                                             func_cb, data);
+     }
+   edje_object_signal_callback_del_full(wd->clk, emission, source, func_cb,
+                                        data);
+}
+
+static void
+_timediff_set(Widget_Data *wd)
+{
+   struct timeval timev;
+   struct tm *tm;
+   time_t tt;
+   gettimeofday(&timev, NULL);
+   tt = (time_t)(timev.tv_sec);
+   tzset();
+   tm = localtime(&tt);
+   wd->timediff = (((wd->hrs - tm->tm_hour) * 60 +
+           wd->min - tm->tm_min) * 60) + wd->sec - tm->tm_sec;
+}
+
+static Eina_Bool
+_ticker(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   double t;
+   struct timeval timev;
+   struct tm *tm;
+   time_t tt;
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   gettimeofday(&timev, NULL);
+   t = ((double)(1000000 - timev.tv_usec)) / 1000000.0;
+   wd->ticker = ecore_timer_add(t, _ticker, data);
+   if (!wd->edit)
+     {
+       tt = (time_t)(timev.tv_sec) + wd->timediff;
+       tzset();
+       tm = localtime(&tt);
+       if (tm)
+         {
+            wd->hrs = tm->tm_hour;
+            wd->min = tm->tm_min;
+            wd->sec = tm->tm_sec;
+            _time_update(data);
+         }
+     }
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_signal_clock_val_up(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) goto clock_val_up_exit_on_error;
+   if (!wd->edit) goto clock_val_up_cancel;
+   if (!wd->sel_obj) goto clock_val_up_cancel;
+   if (wd->sel_obj == wd->digit[0])
+     {
+       wd->hrs = wd->hrs + 10;
+       if (wd->hrs >= 24) wd->hrs -= 24;
+     }
+   if (wd->sel_obj == wd->digit[1])
+     {
+       wd->hrs = wd->hrs + 1;
+       if (wd->hrs >= 24) wd->hrs -= 24;
+     }
+   if (wd->sel_obj == wd->digit[2])
+     {
+       wd->min = wd->min + 10;
+       if (wd->min >= 60) wd->min -= 60;
+     }
+   if (wd->sel_obj == wd->digit[3])
+     {
+       wd->min = wd->min + 1;
+       if (wd->min >= 60) wd->min -= 60;
+     }
+   if (wd->sel_obj == wd->digit[4])
+     {
+       wd->sec = wd->sec + 10;
+       if (wd->sec >= 60) wd->sec -= 60;
+     }
+   if (wd->sel_obj == wd->digit[5])
+     {
+       wd->sec = wd->sec + 1;
+       if (wd->sec >= 60) wd->sec -= 60;
+     }
+   if (wd->sel_obj == wd->ampm)
+     {
+       wd->hrs = wd->hrs + 12;
+       if (wd->hrs > 23) wd->hrs -= 24;
+     }
+   wd->interval = wd->interval / 1.05;
+   ecore_timer_interval_set(wd->spin, wd->interval);
+   _time_update(data);
+   evas_object_smart_callback_call(data, "changed", NULL);
+   return ECORE_CALLBACK_RENEW;
+clock_val_up_cancel:
+   wd->spin = NULL;
+clock_val_up_exit_on_error:
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_signal_clock_val_down(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) goto clock_val_down_exit_on_error;
+   if (!wd->edit) goto clock_val_down_cancel;
+   if (!wd->sel_obj) goto clock_val_down_cancel;
+   if (wd->sel_obj == wd->digit[0])
+     {
+       wd->hrs = wd->hrs - 10;
+       if (wd->hrs < 0) wd->hrs += 24;
+     }
+   if (wd->sel_obj == wd->digit[1])
+     {
+       wd->hrs = wd->hrs - 1;
+       if (wd->hrs < 0) wd->hrs += 24;
+     }
+   if (wd->sel_obj == wd->digit[2])
+     {
+       wd->min = wd->min - 10;
+       if (wd->min < 0) wd->min += 60;
+     }
+   if (wd->sel_obj == wd->digit[3])
+     {
+       wd->min = wd->min - 1;
+       if (wd->min < 0) wd->min += 60;
+     }
+   if (wd->sel_obj == wd->digit[4])
+     {
+       wd->sec = wd->sec - 10;
+       if (wd->sec < 0) wd->sec += 60;
+     }
+   if (wd->sel_obj == wd->digit[5])
+     {
+       wd->sec = wd->sec - 1;
+       if (wd->sec < 0) wd->sec += 60;
+     }
+   if (wd->sel_obj == wd->ampm)
+     {
+       wd->hrs = wd->hrs - 12;
+       if (wd->hrs < 0) wd->hrs += 24;
+     }
+   wd->interval = wd->interval / 1.05;
+   ecore_timer_interval_set(wd->spin, wd->interval);
+   _time_update(data);
+   evas_object_smart_callback_call(data, "changed", NULL);
+   return ECORE_CALLBACK_RENEW;
+clock_val_down_cancel:
+   wd->spin = NULL;
+clock_val_down_exit_on_error:
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_signal_clock_val_up_start(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->sel_obj = obj;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _signal_clock_val_up, data);
+   _signal_clock_val_up(data);
+}
+
+static void
+_signal_clock_val_down_start(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->sel_obj = obj;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _signal_clock_val_down, data);
+   _signal_clock_val_down(data);
+}
+
+static void
+_signal_clock_val_change_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = NULL;
+   wd->sel_obj = NULL;
+}
+
+static void
+_time_update(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Edje_Message_Int msg;
+   int ampm = 0;
+   const char *style = elm_widget_style_get(obj);
+   if (!wd) return;
+   if ((wd->cur.seconds != wd->seconds) || (wd->cur.am_pm != wd->am_pm) ||
+       (wd->cur.edit != wd->edit) || (wd->cur.digedit != wd->digedit))
+     {
+       int i;
+       Evas_Coord mw, mh;
+
+       for (i = 0; i < 6; i++)
+         {
+            if (wd->digit[i])
+              {
+                 evas_object_del(wd->digit[i]);
+                 wd->digit[i] = NULL;
+              }
+         }
+       if (wd->ampm)
+         {
+            evas_object_del(wd->ampm);
+            wd->ampm = NULL;
+         }
+
+       if ((wd->seconds) && (wd->am_pm))
+         _elm_theme_object_set(obj, wd->clk, "clock", "base-all", style);
+       else if (wd->seconds)
+         _elm_theme_object_set(obj, wd->clk, "clock", "base-seconds", style);
+       else if (wd->am_pm)
+         _elm_theme_object_set(obj, wd->clk, "clock", "base-am_pm", style);
+       else
+         _elm_theme_object_set(obj, wd->clk, "clock", "base", style);
+       edje_object_scale_set(wd->clk, elm_widget_scale_get(obj) * 
+                              _elm_config->scale);
+
+       for (i = 0; i < 6; i++)
+         {
+            char buf[16];
+
+            if ((!wd->seconds) && (i >= 4)) break;
+            wd->digit[i] = edje_object_add(evas_object_evas_get(wd->clk));
+            _elm_theme_object_set(obj, wd->digit[i], "clock", "flipdigit", style);
+            edje_object_scale_set(wd->digit[i], elm_widget_scale_get(obj) * 
+                                   _elm_config->scale);
+            if ((wd->edit) && (wd->digedit & (1 << i)))
+              edje_object_signal_emit(wd->digit[i], "elm,state,edit,on", "elm");
+            edje_object_signal_callback_add(wd->digit[i], "elm,action,up,start",
+                                            "", _signal_clock_val_up_start, obj);
+            edje_object_signal_callback_add(wd->digit[i], "elm,action,up,stop",
+                                            "", _signal_clock_val_change_stop, obj);
+            edje_object_signal_callback_add(wd->digit[i], "elm,action,down,start",
+                                            "", _signal_clock_val_down_start, obj);
+            edje_object_signal_callback_add(wd->digit[i], "elm,action,down,stop",
+                                            "", _signal_clock_val_change_stop, obj);
+            mw = mh = -1;
+            elm_coords_finger_size_adjust(1, &mw, 2, &mh);
+            edje_object_size_min_restricted_calc(wd->digit[i], &mw, &mh, mw, mh);
+            elm_coords_finger_size_adjust(1, &mw, 2, &mh);
+            edje_extern_object_min_size_set(wd->digit[i], mw, mh);
+            snprintf(buf, sizeof(buf), "d%i", i);
+            edje_object_part_swallow(wd->clk , buf, wd->digit[i]);
+            evas_object_show(wd->digit[i]);
+         }
+       if (wd->am_pm)
+         {
+            wd->ampm = edje_object_add(evas_object_evas_get(wd->clk));
+            _elm_theme_object_set(obj, wd->ampm, "clock", "flipampm", style);
+            edje_object_scale_set(wd->ampm, elm_widget_scale_get(obj) * 
+                                   _elm_config->scale);
+            if (wd->edit)
+              edje_object_signal_emit(wd->ampm, "elm,state,edit,on", "elm");
+            edje_object_signal_callback_add(wd->ampm, "elm,action,up,start",
+                                            "", _signal_clock_val_up_start, obj);
+            edje_object_signal_callback_add(wd->ampm, "elm,action,up,stop",
+                                            "", _signal_clock_val_change_stop, obj);
+            edje_object_signal_callback_add(wd->ampm, "elm,action,down,start",
+                                            "", _signal_clock_val_down_start, obj);
+            edje_object_signal_callback_add(wd->ampm, "elm,action,down,stop",
+                                            "", _signal_clock_val_change_stop, obj);
+            mw = mh = -1;
+            elm_coords_finger_size_adjust(1, &mw, 2, &mh);
+            edje_object_size_min_restricted_calc(wd->ampm, &mw, &mh, mw, mh);
+            elm_coords_finger_size_adjust(1, &mw, 2, &mh);
+            edje_extern_object_min_size_set(wd->ampm, mw, mh);
+            edje_object_part_swallow(wd->clk , "ampm", wd->ampm);
+            evas_object_show(wd->ampm);
+         }
+
+       edje_object_size_min_calc(wd->clk, &mw, &mh);
+       evas_object_size_hint_min_set(obj, mw, mh);
+
+       wd->cur.hrs = 0;
+       wd->cur.min = 0;
+       wd->cur.sec = 0;
+       wd->cur.ampm = -1;
+       wd->cur.seconds = wd->seconds;
+       wd->cur.am_pm = wd->am_pm;
+       wd->cur.edit = wd->edit;
+       wd->cur.digedit = wd->digedit;
+     }
+   if (wd->hrs != wd->cur.hrs)
+     {
+       int hrs;
+       int d1, d2, dc1, dc2;
+
+       hrs = wd->hrs;
+       if (wd->am_pm)
+         {
+            if (hrs >= 12)
+              {
+                 if (hrs > 12) hrs -= 12;
+                 ampm = 1;
+              }
+            else if (!hrs) hrs = 12;
+         }
+       d1 = hrs / 10;
+       d2 = hrs % 10;
+       dc1 = wd->cur.hrs / 10;
+       dc2 = wd->cur.hrs % 10;
+       if (d1 != dc1)
+         {
+            msg.val = d1;
+            edje_object_message_send(wd->digit[0], EDJE_MESSAGE_INT, 1, &msg);
+         }
+       if (d2 != dc2)
+         {
+            msg.val = d2;
+            edje_object_message_send(wd->digit[1], EDJE_MESSAGE_INT, 1, &msg);
+         }
+       wd->cur.hrs = hrs;
+     }
+   if (wd->min != wd->cur.min)
+     {
+       int d1, d2, dc1, dc2;
+
+       d1 = wd->min / 10;
+       d2 = wd->min % 10;
+       dc1 = wd->cur.min / 10;
+       dc2 = wd->cur.min % 10;
+       if (d1 != dc1)
+         {
+            msg.val = d1;
+            edje_object_message_send(wd->digit[2], EDJE_MESSAGE_INT, 1, &msg);
+         }
+       if (d2 != dc2)
+         {
+            msg.val = d2;
+            edje_object_message_send(wd->digit[3], EDJE_MESSAGE_INT, 1, &msg);
+         }
+       wd->cur.min = wd->min;
+     }
+   if (wd->seconds)
+     {
+       if (wd->sec != wd->cur.sec)
+         {
+            int d1, d2, dc1, dc2;
+
+            d1 = wd->sec / 10;
+            d2 = wd->sec % 10;
+            dc1 = wd->cur.sec / 10;
+            dc2 = wd->cur.sec % 10;
+            if (d1 != dc1)
+              {
+                 msg.val = d1;
+                 edje_object_message_send(wd->digit[4], EDJE_MESSAGE_INT, 1, &msg);
+              }
+            if (d2 != dc2)
+              {
+                 msg.val = d2;
+                 edje_object_message_send(wd->digit[5], EDJE_MESSAGE_INT, 1, &msg);
+              }
+            wd->cur.sec = wd->sec;
+         }
+     }
+   else
+     wd->cur.sec = -1;
+
+   if (wd->am_pm)
+     {
+       if (wd->hrs >= 12) ampm = 1;
+       if (ampm != wd->cur.ampm)
+         {
+            if (wd->cur.ampm != ampm)
+              {
+                 msg.val = ampm;
+                 edje_object_message_send(wd->ampm, EDJE_MESSAGE_INT, 1, &msg);
+              }
+            wd->cur.ampm = ampm;
+         }
+     }
+   else
+     wd->cur.ampm = -1;
+}
+
+/**
+ * Add a new clock to the parent
+ *
+ * @param parent The parent object
+ *
+ * This function inserts a clock widget on a given canvas to show a
+ * animated clock.
+ *
+ * @ingroup Clock
+ */
+EAPI Evas_Object *
+elm_clock_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "clock");
+   elm_widget_type_set(obj, "clock");
+   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_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+
+   wd->clk = edje_object_add(e);
+   elm_widget_resize_object_set(obj, wd->clk);
+
+   wd->cur.ampm = -1;
+   wd->cur.seconds = EINA_TRUE;
+   wd->cur.am_pm = EINA_TRUE;
+   wd->cur.edit = EINA_TRUE;
+   wd->cur.digedit = ELM_CLOCK_NONE;
+   wd->first_interval = 0.85;
+   wd->timediff = 0;
+
+   _time_update(obj);
+   _ticker(obj);
+
+   return obj;
+}
+
+/**
+ * Set the clock time
+ *
+ * @param obj The clock object
+ * @param hrs The hours to set
+ * @param min The minutes to set
+ * @param sec The secondes to set
+ *
+ * This function updates the time that is showed by the clock widget
+ *
+ * @ingroup Clock
+ */
+EAPI void
+elm_clock_time_set(Evas_Object *obj, int hrs, int min, int sec)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hrs = hrs;
+   wd->min = min;
+   wd->sec = sec;
+   _timediff_set(wd);
+   _time_update(obj);
+}
+
+/**
+ * Get clock time
+ *
+ * @param obj The clock object
+ * @param hrs Pointer to the variable to get the hour of this clock
+ * object
+ * @param min Pointer to the variable to get the minute of this clock
+ * object
+ * @param sec Pointer to the variable to get the second of this clock
+ * object
+ *
+ * This function gets the time set of the clock widget and returns it
+ * on the variables passed as the arguments to function
+ *
+ * @ingroup Clock
+ */
+EAPI void
+elm_clock_time_get(const Evas_Object *obj, int *hrs, int *min, int *sec)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   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 clock settings can be edited
+ *
+ * @param obj The clock object
+ * @param edit Bool option for edited (1 = yes, 0 = no)
+ *
+ * This function sets if the clock settings can be edited or not.
+ * By default or if digit_edit option was previously set to ELM_CLOCK_NONE,
+ * all digits are editable. To choose what digits to make editable
+ * use elm_clock_digit_edit_set().
+ *
+ * @ingroup Clock
+ */
+EAPI void
+elm_clock_edit_set(Evas_Object *obj, Eina_Bool edit)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->edit = edit;
+   if (!edit)
+     _timediff_set(wd);
+   if ((edit) && (wd->digedit == ELM_CLOCK_NONE))
+     elm_clock_digit_edit_set(obj, ELM_CLOCK_ALL);
+   else
+     _time_update(obj);
+}
+
+/**
+ * Get if the clock settings can be edited
+ *
+ * @param obj The clock object
+ * @return Bool option for edited (1 = yes, 0 = no)
+ *
+ * This function gets if the clock settings can be edited or not.
+ *
+ * @ingroup Clock
+ */
+EAPI Eina_Bool
+elm_clock_edit_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->edit;
+}
+
+/**
+ * Set what digits of the clock are editable
+ *
+ * @param obj The clock object
+ * @param digedit Bit mask indicating the digits to edit
+ *
+ * If the digedit param is ELM_CLOCK_NONE, editing will be disabled.
+ *
+ * @ingroup Clock
+ */
+EAPI void
+elm_clock_digit_edit_set(Evas_Object *obj, Elm_Clock_Digedit digedit)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->digedit = digedit;
+   if (digedit == ELM_CLOCK_NONE)
+     elm_clock_edit_set(obj, EINA_FALSE);
+   else
+     _time_update(obj);
+}
+
+/**
+ * Get what digits of the clock are editable
+ *
+ * @param obj The clock object
+ * @return Bit mask indicating the digits.
+ *
+ * @ingroup Clock
+ */
+EAPI Elm_Clock_Digedit
+elm_clock_digit_edit_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->digedit;
+}
+
+/**
+ * Set if the clock shows hours in military or am/pm mode
+ *
+ * @param obj The clock object
+ * @param am_pm Bool option for the hours mode
+ * (1 = am/pm, 0 = military)
+ *
+ * This function sets the clock to show hours in military or am/pm
+ * mode. Some countries like Brazil the military mode (00-24h-format)
+ * is used in opposition to the USA where the am/pm mode is more
+ * common used.
+ *
+ * @ingroup Clock
+ */
+EAPI void
+elm_clock_show_am_pm_set(Evas_Object *obj, Eina_Bool am_pm)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->am_pm = am_pm;
+   _time_update(obj);
+}
+
+/**
+ * Get if the clock shows hours in military or am/pm mode
+ *
+ * @param obj The clock object
+ * @return Bool option for the hours mode
+ * (1 = am/pm, 0 = military)
+ *
+ * This function gets if the clock show hours in military or am/pm
+ * mode. Some countries like Brazil the military mode (00-24h-format)
+ * is used in opposition to the USA where the am/pm mode is more
+ * common used.
+ *
+ * @ingroup Clock
+ */
+EAPI Eina_Bool
+elm_clock_show_am_pm_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->am_pm;
+}
+
+/**
+ * Set if the clock shows hour with the seconds
+ *
+ * @param obj The clock object
+ * @param seconds Bool option for the show seconds
+ * (1 = show seconds, 0 = not show seconds)
+ *
+ * This function sets the clock to show or not to show the elapsed
+ * seconds.
+ *
+ * @ingroup Clock
+ */
+EAPI void
+elm_clock_show_seconds_set(Evas_Object *obj, Eina_Bool seconds)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->seconds = seconds;
+   _time_update(obj);
+}
+
+/**
+ * Get if the clock shows hour with the seconds
+ *
+ * @param obj The clock object
+ * @return Bool option for the show seconds
+ * (1 = show seconds, 0 = not show seconds)
+ *
+ * This function gets if the clock show or not show the elapsed
+ * seconds.
+ *
+ * @ingroup Clock
+ */
+EAPI Eina_Bool
+elm_clock_show_seconds_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->seconds;
+}
+
+/**
+ * Set the interval for the clock
+ *
+ * @param obj The clock object
+ * @param interval The interval value in seconds
+ *
+ * The interval value is decreased while the user increments or decrements
+ * the clock value. The next interval value is the previous interval / 1.05,
+ * so it speed up a bit. Default value is 0.85 seconds.
+ *
+ * @ingroup Clock
+ */
+EAPI void
+elm_clock_interval_set(Evas_Object *obj, double interval)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->first_interval = interval;
+}
+
+/**
+ * Get the interval of the clock
+ *
+ * @param obj The clock object
+ * @return The value of the first interval in seconds
+ *
+ * The interval value is decreased while the user increments or decrements
+ * the clock value. The next interval value is the previous interval / 1.05,
+ * so it speed up a bit. Default value is 0.85 seconds.
+ *
+ * @ingroup Clock
+ */
+EAPI double
+elm_clock_interval_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->first_interval;
+}
diff --git a/src/lib/elm_cnp_helper.c b/src/lib/elm_cnp_helper.c
new file mode 100644 (file)
index 0000000..9d8fb1c
--- /dev/null
@@ -0,0 +1,1779 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#include <sys/mman.h>
+
+#ifdef HAVE_ELEMENTARY_X
+
+#define ARRAYINIT(foo)  [foo] =
+
+//#define DEBUGON 1
+
+
+#ifdef DEBUGON
+# define cnp_debug(x...) fprintf(stderr, __FILE__": " x)
+#else
+# define cnp_debug(x...)
+#endif
+
+#define PROVIDER_SET "__elm_cnp_provider_set"
+
+typedef struct _Paste_Image   Paste_Image;
+typedef struct _Cnp_Selection Cnp_Selection;
+typedef struct _Escape        Escape;
+typedef struct _Tmp_Info      Tmp_Info;
+typedef struct _Cnp_Atom      Cnp_Atom;
+typedef struct _Saved_Type    Saved_Type;
+typedef struct _Dropable      Dropable;
+
+typedef Eina_Bool (*Converter_Fn_Cb)     (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+typedef int       (*Response_Handler_Cb) (Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
+typedef int       (*Notify_Handler_Cb)   (Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
+
+enum
+{
+   CNP_ATOM_TARGETS = 0,
+   CNP_ATOM_text_uri,
+   CNP_ATOM_text_urilist,
+   CNP_ATOM_text_x_vcard,
+   CNP_ATOM_image_png,
+   CNP_ATOM_image_jpeg,
+   CNP_ATOM_image_bmp,
+   CNP_ATOM_image_gif,
+   CNP_ATOM_image_tiff,
+   CNP_ATOM_image_svg,
+   CNP_ATOM_image_xpm,
+   CNP_ATOM_image_tga,
+   CNP_ATOM_image_ppm,
+   CNP_ATOM_XELM,
+   CNP_ATOM_text_html_utf8,
+   CNP_ATOM_text_html,
+   CNP_ATOM_UTF8STRING,
+   CNP_ATOM_STRING,
+   CNP_ATOM_TEXT,
+   CNP_ATOM_text_plain_utf8,
+   CNP_ATOM_text_plain,
+   
+   CNP_N_ATOMS,
+};
+
+struct _Paste_Image
+{
+   Evas_Object *entry;
+   const char  *tag;
+   const char  *file;
+   Evas_Object *img;
+};
+
+struct _Cnp_Selection
+{
+   const char      *debug;
+   Evas_Object     *widget;
+   char            *selbuf;
+   Evas_Object     *requestwidget;
+   void            *udata;
+   Elm_Sel_Format   requestformat;
+   Elm_Drop_Cb      datacb;
+   Eina_Bool      (*set)     (Ecore_X_Window, const void *data, int size);
+   Eina_Bool      (*clear)   (void);
+   void           (*request) (Ecore_X_Window, const char *target);
+
+   Elm_Sel_Format    format;
+   Ecore_X_Selection ecore_sel;
+   
+   Eina_Bool         active : 1;
+};
+
+struct _Escape
+{
+   const char *escape;
+   const char  value;
+};
+
+struct _Tmp_Info
+{
+   char *filename;
+   void *map;
+   int   fd;
+   int   len;
+};
+
+struct _Cnp_Atom
+{
+   const char          *name;
+   Elm_Sel_Format       formats;
+   /* Called by ecore to do conversion */
+   Converter_Fn_Cb      converter;
+   Response_Handler_Cb  response;
+   Notify_Handler_Cb    notify;
+   /* Atom */
+   Ecore_X_Atom         atom;
+};
+
+struct _Saved_Type
+{
+   const char  **types;
+   Paste_Image  *pi;
+   int           ntypes;
+   int           x, y;
+   Eina_Bool     textreq: 1;
+};
+
+struct _Dropable
+{
+   Evas_Object     *obj;
+   /* FIXME: Cache window */
+   Elm_Sel_Format   types;
+   Elm_Drop_Cb      dropcb;
+   void            *cbdata;
+};
+
+static Tmp_Info *elm_cnp_tempfile_create(int size);
+static int tmpinfo_free(Tmp_Info *tmp);
+
+static Eina_Bool _elm_cnp_init(void);
+static Eina_Bool selection_clear(void *udata __UNUSED__, int type, void *event);
+static Eina_Bool selection_notify(void *udata __UNUSED__, int type, void *event);
+static char *remove_tags(const char *p, int *len);
+static char *mark_up(const char *start, int inlen, int *lenp);
+
+static Evas_Object *image_provider(void *images, Evas_Object *entry, const char *item);
+static void entry_deleted(void *images, Evas *e, Evas_Object *entry, void *unused);
+
+
+static Eina_Bool targets_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool html_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool edje_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool uri_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool image_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool vcard_send(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+
+static int response_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
+
+static int notify_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
+static int notify_handler_text(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
+static int notify_handler_image(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
+static int notify_handler_uri(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
+static int notify_handler_html(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
+static int vcard_receive(Cnp_Selection *sed, Ecore_X_Event_Selection_Notify *notify);
+
+static Paste_Image *pasteimage_alloc(const char *file, int pathlen);
+static Eina_Bool pasteimage_append(Paste_Image *pi, Evas_Object *entry);
+static void pasteimage_free(Paste_Image *pi);
+
+/* Optimisation: Turn this into a 256 byte table:
+ *     then can lookup in one index, not N checks */
+static const Escape escapes[] = {
+   { "<br>",   '\n' },
+   { "<\t>",   '\t' },
+   { "gt;",    '>'  },
+   { "lt;",    '<'  },
+   { "amp;",   '&'  },
+   { "quot;",  '\'' },
+   { "dquot;", '"'  }
+};
+#define N_ESCAPES ((int)(sizeof(escapes) / sizeof(escapes[0])))
+
+static const char *image_extensions[] =
+{
+   ".png",
+   ".jpg", ".jpeg", ".jpe", ".jfif", ".jfi",
+   ".bmp",
+   ".xpm",
+   ".ppm", "pgm", ".pbm", ".pnm",
+   ".gif",
+   ".tif", ".tiff",
+   ".svg", ".svg.gz",
+   ".tga", ".targa",
+   
+   NULL
+};
+
+static Cnp_Atom atoms[CNP_N_ATOMS] = {
+   [CNP_ATOM_TARGETS] = {
+      "TARGETS",
+      (Elm_Sel_Format) -1, // everything
+      targets_converter,
+      response_handler_targets,
+      notify_handler_targets,
+      0
+   },
+   [CNP_ATOM_XELM] =  {
+      "application/x-elementary-markup",
+      ELM_SEL_FORMAT_MARKUP,
+      edje_converter,
+      NULL,
+      NULL,
+      0
+   },
+   [CNP_ATOM_text_uri] = {
+      "text/uri",
+      ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE, /* Either images or entries */
+      uri_converter,
+      NULL,
+      notify_handler_uri,
+      0
+   },
+   [CNP_ATOM_text_urilist] = {
+      "text/uri-list",
+      ELM_SEL_FORMAT_IMAGE,
+      uri_converter,
+      NULL,
+      notify_handler_uri,
+      0
+   },
+   [CNP_ATOM_text_x_vcard] = {
+      "text/x-vcard",
+      ELM_SEL_FORMAT_VCARD,
+      vcard_send, NULL,
+      vcard_receive, 0
+   },
+   [CNP_ATOM_image_png] = {
+      "image/png",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,
+      0
+   },
+   [CNP_ATOM_image_jpeg] = {
+      "image/jpeg",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_image_bmp] = {
+      "image/x-ms-bmp",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_image_gif] = {
+      "image/gif",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_image_tiff] = {
+      "image/tiff",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_image_svg] = {
+      "image/svg+xml",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_image_xpm] = {
+      "image/x-xpixmap",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_image_tga] = {
+      "image/x-tga",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_image_ppm] = {
+      "image/x-portable-pixmap",
+      ELM_SEL_FORMAT_IMAGE,
+      image_converter,
+      NULL,
+      notify_handler_image,/* Raw image data is the same */
+      0
+   },
+   [CNP_ATOM_text_html_utf8] = {
+      "text/html;charset=utf-8",
+      ELM_SEL_FORMAT_HTML,
+      html_converter,
+      NULL,
+      notify_handler_html,
+      0
+   },
+   [CNP_ATOM_text_html] = {
+      "text/html",
+      ELM_SEL_FORMAT_HTML,
+      html_converter,
+      NULL,
+      notify_handler_html, /* No encoding: Webkit only */
+      0
+   },
+   [CNP_ATOM_UTF8STRING] = {
+      "UTF8_STRING",
+      ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
+      text_converter,
+      NULL,
+      notify_handler_text,
+      0
+   },
+   [CNP_ATOM_STRING] = {
+      "STRING",
+      ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
+      text_converter,
+      NULL,
+      notify_handler_text,
+      0
+   },
+   [CNP_ATOM_TEXT] = {
+      "TEXT",
+      ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
+      text_converter,
+      NULL,
+      NULL,
+      0
+   },
+   [CNP_ATOM_text_plain_utf8] = {
+      "text/plain;charset=utf-8",
+      ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
+      text_converter,
+      NULL,
+      NULL,
+      0
+   },
+   [CNP_ATOM_text_plain] = {
+      "text/plain",
+      ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
+      text_converter,
+      NULL,
+      NULL,
+      0
+   },
+};
+
+static Cnp_Selection selections[ELM_SEL_MAX] = {
+   ARRAYINIT(ELM_SEL_PRIMARY) {
+      .debug = "Primary",
+      .ecore_sel = ECORE_X_SELECTION_PRIMARY,
+      .set = ecore_x_selection_primary_set,
+      .clear = ecore_x_selection_primary_clear,
+      .request = ecore_x_selection_primary_request,
+   },
+   ARRAYINIT(ELM_SEL_SECONDARY) {
+      .debug = "Secondary",
+      .ecore_sel = ECORE_X_SELECTION_SECONDARY,
+      .set = ecore_x_selection_secondary_set,
+      .clear = ecore_x_selection_secondary_clear,
+      .request = ecore_x_selection_secondary_request,
+   },
+   ARRAYINIT(ELM_SEL_CLIPBOARD) {
+      .debug = "Clipboard",
+      .ecore_sel = ECORE_X_SELECTION_CLIPBOARD,
+      .set = ecore_x_selection_clipboard_set,
+      .clear = ecore_x_selection_clipboard_clear,
+      .request = ecore_x_selection_clipboard_request,
+   },
+   ARRAYINIT(ELM_SEL_XDND) {
+      .debug = "XDnD",
+      .ecore_sel = ECORE_X_SELECTION_XDND,
+      .request = ecore_x_selection_xdnd_request,
+   },
+};
+
+/* Data for DND in progress */
+static Saved_Type savedtypes =  { NULL, NULL, 0, 0, 0, EINA_FALSE };
+
+static void (*dragdonecb) (void *data, Evas_Object *obj) = NULL;
+static void *dragdonedata = NULL;
+
+static int _elm_cnp_init_count = 0;
+/* FIXME: who left this out of XAtoms.h */
+static Ecore_X_Atom clipboard_atom;
+
+static Eina_List *pastedimages = NULL;
+
+/**
+ * Drag & Drop functions
+ */
+
+/* FIXME: Way too many globals */
+static Eina_List *drops = NULL;
+static Evas_Object *dragwin = NULL;
+static int _dragx = 0, _dragy = 0;
+static Ecore_Event_Handler *handler_pos = NULL;
+static Ecore_Event_Handler *handler_drop = NULL;
+static Ecore_Event_Handler *handler_enter = NULL;
+static Ecore_Event_Handler *handler_status = NULL;
+
+#endif
+
+/* Stringshared, so I can just compare pointers later */
+static const char *text_uri;
+
+Eina_Bool
+elm_selection_set(Elm_Sel_Type selection, Evas_Object *widget, Elm_Sel_Format format, const char *selbuf)
+{
+#ifdef HAVE_ELEMENTARY_X
+   Cnp_Selection *sel;
+
+   if ((unsigned int)selection >= (unsigned int)ELM_SEL_MAX) return EINA_FALSE;
+   if (!_elm_cnp_init_count) _elm_cnp_init();
+   if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
+      return elm_selection_clear(selection, widget);
+
+   sel = selections + selection;
+
+   sel->active = 1;
+   sel->widget = widget;
+
+   sel->set(elm_win_xwindow_get(widget),&selection,sizeof(Elm_Sel_Type));
+   sel->format = format;
+   sel->selbuf = selbuf ? strdup(selbuf) : NULL;
+
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+Eina_Bool
+elm_selection_clear(Elm_Sel_Type selection, Evas_Object *widget)
+{
+#ifdef HAVE_ELEMENTARY_X
+   Cnp_Selection *sel;
+
+   if ((unsigned int)selection >= (unsigned int)ELM_SEL_MAX) return EINA_FALSE;
+   if (!_elm_cnp_init_count) _elm_cnp_init();
+
+   sel = selections + selection;
+
+   /* No longer this selection: Consider it gone! */
+   if ((!sel->active) || (sel->widget != widget)) return EINA_TRUE;
+
+   sel->active = 0;
+   sel->widget = NULL;
+   sel->clear();
+
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+Eina_Bool
+elm_selection_get(Elm_Sel_Type selection, Elm_Sel_Format format,
+                       Evas_Object *widget, Elm_Drop_Cb datacb, void *udata)
+{
+#ifdef HAVE_ELEMENTARY_X
+   Evas_Object *top;
+   Cnp_Selection *sel;
+
+   if ((unsigned int)selection >= (unsigned int)ELM_SEL_MAX) return EINA_FALSE;
+   if (!_elm_cnp_init_count) _elm_cnp_init();
+
+   sel = selections + selection;
+   top = elm_widget_top_get(widget);
+   if (!top) return EINA_FALSE;
+
+   sel->requestformat = format;
+   sel->requestwidget = widget;
+   sel->request(elm_win_xwindow_get(top), ECORE_X_SELECTION_TARGET_TARGETS);
+   sel->datacb = datacb;
+   sel->udata = udata;
+
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+#ifdef HAVE_ELEMENTARY_X
+
+static Eina_Bool
+_elm_cnp_init(void)
+{
+   int i;
+   
+   if (_elm_cnp_init_count++) return EINA_TRUE;
+   for (i = 0; i < CNP_N_ATOMS; i++)
+     {
+       atoms[i].atom = ecore_x_atom_get(atoms[i].name);
+       ecore_x_selection_converter_atom_add(atoms[i].atom,
+                                             atoms[i].converter);
+     }
+   clipboard_atom = ecore_x_atom_get("CLIPBOARD");
+
+   ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, selection_clear, NULL);
+   ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, selection_notify, NULL);
+   
+   text_uri = eina_stringshare_add("text/uri-list");
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+selection_clear(void *udata __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_X_Event_Selection_Clear *ev = event;
+   Cnp_Selection *sel;
+   int i;
+   
+   for (i = 0; i < ELM_SEL_MAX; i++)
+     {
+       if (selections[i].ecore_sel == ev->selection) break;
+     }
+   cnp_debug("selection %d clear\n", i);
+   /* Not me... Don't care */
+   if (i == ELM_SEL_MAX) return ECORE_CALLBACK_PASS_ON;
+
+   sel = selections + i;
+   sel->active = 0;
+   sel->widget = NULL;
+   sel->selbuf = NULL;
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+
+/*
+ * Response to a selection notify:
+ *     - So we have asked for the selection list.
+ *     - If it's the targets list, parse it, and fire of what we want,
+ *     else it's the data we want.
+ */
+static Eina_Bool
+selection_notify(void *udata __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_X_Event_Selection_Notify *ev = event;
+   Cnp_Selection *sel;
+   int i;
+   
+   cnp_debug("selection notify callback: %d\n",ev->selection);
+   switch (ev->selection)
+     {
+      case ECORE_X_SELECTION_CLIPBOARD:
+        sel = selections + ELM_SEL_CLIPBOARD;
+        break;
+      case ECORE_X_SELECTION_PRIMARY:
+        sel = selections + ELM_SEL_PRIMARY;
+        break;
+      case ECORE_X_SELECTION_SECONDARY:
+        sel = selections + ELM_SEL_SECONDARY;
+        break;
+      case ECORE_X_SELECTION_XDND:
+        sel = selections + ELM_SEL_XDND;
+        break;
+      default:
+        return ECORE_CALLBACK_PASS_ON;
+     }
+   cnp_debug("Target is %s\n", ev->target);
+   
+   for (i = 0; i < CNP_N_ATOMS; i++)
+     {
+       if (!strcmp(ev->target, atoms[i].name))
+         {
+            if (atoms[i].notify)
+               {
+                  cnp_debug("Found something: %s\n", atoms[i].name);
+                 atoms[i].notify(sel, ev);
+               } 
+             else 
+               {
+                 cnp_debug("Ignored: No handler!\n");
+               }
+         }
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+
+
+static Eina_Bool
+targets_converter(char *target __UNUSED__, void *data, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
+{
+   int i,count;
+   Ecore_X_Atom *aret;
+   Cnp_Selection *sel;
+   
+   if (!data_ret) return EINA_FALSE;
+
+   sel = selections + *((int *)data);
+
+   for (i = 0, count = 0; i < CNP_N_ATOMS ; i++)
+     {
+       if (sel->format & atoms[i].formats) count++;
+     }
+
+   aret = malloc(sizeof(Ecore_X_Atom) * count);
+   for (i = 0, count = 0; i < CNP_N_ATOMS; i++)
+     {
+       if (sel->format & atoms[i].formats) aret[count ++] = atoms[i].atom;
+     }
+
+   *data_ret = aret;
+   if (typesize) *typesize = 32 /* urk */;
+   if (ttype) *ttype = ECORE_X_ATOM_ATOM;
+   if (size_ret) *size_ret = count;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+image_converter(char *target __UNUSED__, void *data __UNUSED__, int size __UNUSED__, void **data_ret __UNUSED__, int *size_ret __UNUSED__, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
+{
+   cnp_debug("Image converter called\n");
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+vcard_send(char *target __UNUSED__, void *data __UNUSED__, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
+{
+   Cnp_Selection *sel;
+
+   cnp_debug("Vcard send called\n");
+   
+   sel = selections + *((int *)data);
+
+   if (data_ret) *data_ret = strdup(sel->selbuf);
+   if (size_ret) *size_ret = strlen(sel->selbuf);
+
+   return EINA_TRUE;
+}
+/*
+ * Callback to handle a targets response on a selection request:
+ * So pick the format we'd like; and then request it.
+ */
+static int
+notify_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
+{
+   Ecore_X_Selection_Data_Targets *targets;
+   Ecore_X_Atom *atomlist;
+   int i, j;
+   
+   targets = notify->data;
+   atomlist = (Ecore_X_Atom *)(targets->data.data);
+
+   for (j = 1; j < CNP_N_ATOMS; j++)
+     {
+       cnp_debug("\t%s %d\n", atoms[j].name, atoms[j].atom);
+       if (!(atoms[j].formats & sel->requestformat)) continue;
+       for (i = 0; i < targets->data.length; i++)
+         {
+            if ((atoms[j].atom == atomlist[i]) && (atoms[j].notify))
+              {
+                 cnp_debug("Atom %s matches\n",atoms[j].name);
+                 goto done;
+              }
+         }
+     }
+
+   cnp_debug("Couldn't find anything that matches\n");
+   return ECORE_CALLBACK_PASS_ON;
+
+   done:
+   cnp_debug("Sending request for %s\n",atoms[j].name);
+   sel->request(elm_win_xwindow_get(sel->requestwidget), atoms[j].name);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static int
+response_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
+{
+   Ecore_X_Selection_Data_Targets *targets;
+   Ecore_X_Atom *atomlist;
+   Evas_Object *top;
+   int i,j;
+
+   targets = notify->data;
+   atomlist = (Ecore_X_Atom *)(targets->data.data);
+
+   /* Start from 1: Skip targets */
+   for (j = 1 ; j < CNP_N_ATOMS ; j ++)
+     {
+       if (!(atoms[j].formats & sel->requestformat)) continue;
+       for (i = 0 ; i < targets->data.length ; i ++)
+         {
+            if ((atoms[j].atom == atomlist[i]) && (atoms[j].response))
+               {
+                 /* Found a match: Use it */
+                 goto found;
+               }
+          }
+     }
+found:
+   if (j == CNP_N_ATOMS)
+     {
+       cnp_debug("No matching type found\n");
+       return 0;
+     }
+   
+   top = elm_widget_top_get(sel->requestwidget);
+   if (!top) return 0;
+   
+   sel->request(elm_win_xwindow_get(top), atoms[j].name);
+   return 0;
+}
+
+
+static int
+notify_handler_text(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
+{
+   Ecore_X_Selection_Data *data;
+   char *str;
+   
+   data = notify->data;
+   cnp_debug("Notify handler text %d %d %p\n", data->format,data->length, data->data);
+   str = mark_up((char *)data->data, data->length, NULL);
+   cnp_debug("String is %s (from %s)\n", str, data->data);
+   elm_entry_entry_insert(sel->requestwidget, str);
+   free(str);
+   return 0;
+}
+
+
+/**
+ * So someone is pasting an image into my entry or widget...
+ */
+static int
+notify_handler_uri(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
+{
+   Ecore_X_Selection_Data *data;
+   Ecore_X_Selection_Data_Files *files;
+   Paste_Image *pi;
+   char *p, *pp, *ext;
+
+   data = notify->data;
+   cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
+   if (data->content == ECORE_X_SELECTION_CONTENT_FILES)
+     {
+        cnp_debug("got a files list\n");
+        files = notify->data;
+        if (files->num_files > 1)
+          {
+             /* Don't handle many items */
+             cnp_debug("more then one file: Bailing\n");
+             return 0;
+          }
+        p = files->files[0];
+     }
+   else p = (char *)data->data;
+   if (!p)
+     {
+        cnp_debug("Couldn't find a file\n");
+        return 0;
+     }
+   cnp_debug("Got %s\n",p);
+   if (strncmp(p, "file://", 7))
+     {
+        /* Try and continue if it looks sane */
+        if (*p != '/') return 0;
+     }
+   else p += strlen("file://");
+   
+   ext = p + strlen(p);
+   if (ext)
+     {
+        Eina_Bool extok = EINA_FALSE;
+        int i;
+        
+        for (i = 0; image_extensions[i]; i++)
+          {
+             pp = ext - strlen(image_extensions[i]);
+             if ((pp >= p) && (!strcasecmp(pp, image_extensions[i])))
+               {
+                  extok = EINA_TRUE;
+                  break;
+               }
+          }
+        if (!extok)
+          {
+             cnp_debug("No known image format extension, ignoring\n");
+             if (savedtypes.textreq) savedtypes.textreq = 0;
+             return 0;
+          }
+     }
+
+   if (savedtypes.pi) pasteimage_free(savedtypes.pi);
+   pi = pasteimage_alloc(p, strlen(p));
+   if (savedtypes.textreq)
+     {
+        savedtypes.textreq = 0;
+        savedtypes.pi = pi;
+     }
+   else
+     {
+        pasteimage_append(pi, sel->requestwidget);
+        savedtypes.pi = NULL;
+     }
+   return 0;
+}
+
+/**
+ * Just receieved an vcard, either through cut and paste, or dnd.
+ */
+static int
+vcard_receive(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
+{
+   Dropable *dropable;
+   Eina_List *l;
+   Ecore_X_Selection_Data *data;
+
+   data = notify->data;
+   cnp_debug("vcard receive\n");
+
+   if (sel == (selections + ELM_SEL_XDND))
+     {
+        Elm_Selection_Data ddata;
+        
+        cnp_debug("drag & drop\n");
+        /* FIXME: this needs to be generic: Used for all receives */
+        EINA_LIST_FOREACH(drops, l, dropable)
+          {
+             if (dropable->obj == sel->requestwidget) break;
+          }
+        if (!dropable)
+          {
+             cnp_debug("Unable to find drop object");
+             ecore_x_dnd_send_finished();
+             return 0;
+          }
+        dropable = eina_list_data_get(l);
+        ddata.x = savedtypes.x;
+        ddata.y = savedtypes.y;
+        ddata.format = ELM_SEL_FORMAT_VCARD;
+        ddata.data = data->data;
+        ddata.len = data->length;
+        dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
+        ecore_x_dnd_send_finished();
+     }
+   else if (sel->datacb)
+     {
+        Elm_Selection_Data ddata;
+        ddata.x = ddata.y = 0;
+        ddata.format = ELM_SEL_FORMAT_IMAGE;
+        ddata.data = data->data;
+        ddata.len = data->length;
+        sel->datacb(sel->udata, sel->widget, &ddata);
+     }
+   else
+     {
+        cnp_debug("Paste request\n");
+     }
+   
+   return 0;
+
+}
+
+
+static int
+notify_handler_image(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
+{
+   Ecore_X_Selection_Data *data;
+   Tmp_Info *tmp;
+   Paste_Image *pi;
+   
+   cnp_debug("got a png (or a jpeg)!\n");
+   data = notify->data;
+   
+   cnp_debug("Size if %d\n", data->length);
+
+   if (sel->datacb)
+     {
+        Elm_Selection_Data ddata;
+        
+        ddata.x = ddata.y = 0;
+        ddata.format = ELM_SEL_FORMAT_IMAGE;
+        ddata.data = data->data;
+        ddata.len = data->length;
+        sel->datacb(sel->udata, sel->widget, &ddata);
+        return 0;
+     }
+   
+   /* generate tmp name */
+   tmp = elm_cnp_tempfile_create(data->length);
+   memcpy(tmp->map, data->data, data->length);
+   munmap(tmp->map,data->length);
+   
+   /* FIXME: Add to paste image data to clean up */
+   pi = pasteimage_alloc(tmp->filename, strlen(tmp->filename));
+   pasteimage_append(pi, sel->requestwidget);
+
+   tmpinfo_free(tmp);
+   return 0;
+}
+
+
+/**
+ *    Warning: Generic text/html can';t handle it sanely.
+ *    Firefox sends ucs2 (i think).
+ *       chrome sends utf8... blerg
+ */
+static int
+notify_handler_html(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
+{
+   Ecore_X_Selection_Data *data;
+   
+   cnp_debug("Got some HTML: Checking encoding is useful\n");
+   data = notify->data;
+   
+   if (sel->datacb)
+     {
+        Elm_Selection_Data ddata;
+        ddata.x = ddata.y = 0;
+        ddata.format = ELM_SEL_FORMAT_HTML;
+        ddata.data = data->data;
+        ddata.len = data->length;
+        sel->datacb(sel->udata, sel->widget, &ddata);
+        return 0;
+     }
+
+   char *stripstr = NULL;
+   stripstr = malloc(sizeof(char) * (data->length + 1));
+   strncpy(stripstr, (char *)data->data, data->length);
+   stripstr[data->length] = '\0';
+   cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
+   elm_entry_entry_insert(sel->requestwidget, stripstr);
+   free(stripstr);
+   return 0;
+}
+
+
+static Eina_Bool
+text_converter(char *target __UNUSED__, void *data, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
+{
+   Cnp_Selection *sel;
+
+   cnp_debug("text converter\n");
+   sel = selections + *((int *)data);
+   if (!sel->active) return EINA_TRUE;
+   
+   if ((sel->format & ELM_SEL_FORMAT_MARKUP) ||
+       (sel->format & ELM_SEL_FORMAT_HTML))
+     {
+       *data_ret = remove_tags(sel->selbuf, size_ret);
+     }
+   else if (sel->format & ELM_SEL_FORMAT_TEXT)
+     {
+        *data_ret = strdup(sel->selbuf);
+        *size_ret = strlen(sel->selbuf);
+     }
+   else if (sel->format & ELM_SEL_FORMAT_IMAGE)
+     {
+       cnp_debug("Image %s\n", evas_object_type_get(sel->widget));
+       cnp_debug("Elm type: %s\n", elm_object_widget_type_get(sel->widget));
+       evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget), (const char **)data_ret, NULL);
+       if (!*data_ret) *data_ret = strdup("No file");
+       else *data_ret = strdup(*data_ret);
+       *size_ret = strlen(*data_ret);
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+edje_converter(char *target __UNUSED__, void *data, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
+{
+   Cnp_Selection *sel;
+
+   sel = selections + *((int *)data);
+   if (data_ret) *data_ret = strdup(sel->selbuf);
+   if (size_ret) *size_ret = strlen(sel->selbuf);
+
+   return EINA_TRUE;
+}
+
+
+static Eina_Bool
+html_converter(char *target __UNUSED__, void *data, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
+{
+   Cnp_Selection *sel;
+
+   sel = selections + *(int *)data;
+   if (data_ret) *data_ret = strdup(sel->selbuf);
+   if (size_ret) *size_ret = strlen(sel->selbuf);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+uri_converter(char *target __UNUSED__, void *data, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
+{
+    Cnp_Selection *sel;
+    sel = selections + *((int *)data);
+    cnp_debug("Uri converter\n");
+    if (data_ret) *data_ret = strdup(sel->selbuf);
+    if (size_ret) *size_ret = strlen(sel->selbuf);
+    return EINA_TRUE;
+}
+
+/*
+ * Image paste provide
+ */
+
+/* FIXME: Should add provider for each pasted item: Use data to store it
+ * much easier */
+static Evas_Object *
+image_provider(void *images __UNUSED__, Evas_Object *entry, const char *item)
+{
+   Paste_Image *pi;
+   Eina_List *l;
+
+   cnp_debug("image provider for %s called\n", item);
+   EINA_LIST_FOREACH(pastedimages, l, pi)
+     {
+       cnp_debug("is it %s?\n",pi->tag);
+       if (!strcmp(pi->tag, item))
+          {
+            /* Found it */
+            Evas_Object *o;
+            o = evas_object_image_filled_add(evas_object_evas_get(entry));
+            /* FIXME: Handle eets */
+            cnp_debug("file is %s (object is %p)\n", pi->file, o);
+            evas_object_image_file_set(o, pi->file, NULL);
+            evas_object_show(o);
+            return o;
+          }
+     }
+   return NULL;
+}
+
+
+static Paste_Image *
+pasteimage_alloc(const char *file, int pathlen)
+{
+   Paste_Image *pi;
+   int len;
+   char *buf, *filebuf;
+   int prefixlen = strlen("file://");
+
+   pi = calloc(1, sizeof(Paste_Image));
+   if (!pi) return NULL;
+   
+   len = snprintf(NULL, 0, "pasteimage-%p", pi);
+   len++;
+   buf = malloc(len);
+   if (!buf)
+     {
+        free(pi);
+        return NULL;
+     }
+   snprintf(buf, len, "pasteimage-%p", pi);
+   pi->tag = buf;
+   
+   if (file)
+     {
+        if (strstr(file,"file://")) file += prefixlen;
+        filebuf = alloca(pathlen + 1);
+        strncpy(filebuf, file, pathlen);
+        filebuf[pathlen] = 0;
+        pi->file = strdup(filebuf);
+     }
+
+   return pi;
+}
+
+static void
+pasteimage_free(Paste_Image *pi)
+{
+   if (!pi) return;
+   if (pi->file) free((void*)pi->file);
+   if (pi->tag) free((void*)pi->tag);
+   free(pi);
+}
+
+static Eina_Bool
+pasteimage_provider_set(Evas_Object *entry)
+{
+   void *v;
+   const char *type;
+   
+   if (!entry) return EINA_FALSE;
+   type = elm_widget_type_get(entry);
+   cnp_debug("type is %s\n", type);
+   if ((!type) || (strcmp(type, "entry"))) return EINA_FALSE;
+   
+   v = evas_object_data_get(entry, PROVIDER_SET);
+   if (!v)
+     {
+        evas_object_data_set(entry, PROVIDER_SET, pasteimage_provider_set);
+        elm_entry_item_provider_append(entry, image_provider, NULL);
+        evas_object_event_callback_add(entry, EVAS_CALLBACK_FREE,
+                                       entry_deleted, NULL);
+     }
+   return EINA_TRUE;
+}
+
+
+static Eina_Bool
+pasteimage_append(Paste_Image *pi, Evas_Object *entry)
+{
+   char *entrytag;
+   int len;
+   static const char *tagstring = "<item absize=240x180 href=file://%s></item>";
+
+   if (!pi) return EINA_FALSE;
+   if (!entry) return EINA_FALSE;
+
+   pasteimage_provider_set(entry);
+
+   len = strlen(tagstring)+strlen(pi->file);
+
+   pastedimages = eina_list_append(pastedimages, pi);
+   entrytag = alloca(len + 1);
+   snprintf(entrytag, len + 1, tagstring, pi->file);
+   elm_entry_entry_insert(entry, entrytag);
+
+   return EINA_TRUE;
+}
+
+static void
+entry_deleted(void *images __UNUSED__, Evas *e __UNUSED__, Evas_Object *entry, void *unused __UNUSED__)
+{
+   Paste_Image *pi;
+   Eina_List *l,*next;
+
+   EINA_LIST_FOREACH_SAFE(pastedimages, l, next, pi)
+     {
+       if (pi->entry == entry)
+           pastedimages = eina_list_remove_list(pastedimages, l);
+     }
+}
+
+
+static char *
+remove_tags(const char *p, int *len)
+{
+   char *q,*ret;
+   int i;
+   if (!p) return NULL;
+   
+   q = malloc(strlen(p) + 1);
+   if (!q) return NULL;
+   ret = q;
+
+   while (*p)
+     {
+       if ((*p != '<') && (*p != '&')) *q++ = *p++;
+        else if (*p == '<')
+          {
+            if ((p[1] == 'b') && (p[2] == 'r') &&
+                 ((p[3] == ' ') || (p[3] == '/') || (p[3] == '>')))
+               *q++ = '\n';
+            while ((*p) && (*p != '>')) p++;
+            p++;
+          } 
+        else if (*p == '&')
+          {
+            p++;
+            for (i = 0 ; i < N_ESCAPES ; i++)
+               {
+                  if (!strncmp(p,escapes[i].escape, strlen(escapes[i].escape)))
+                    {
+                       p += strlen(escapes[i].escape);
+                      *q = escapes[i].value;
+                      q++;
+                      break;
+                    }
+               }
+            if (i == N_ESCAPES) *q ++= '&';
+          }
+     }
+   *q = 0;
+   if (len) *len = q - ret;
+   return ret;
+}
+
+/* Mark up */
+static char *
+mark_up(const char *start, int inlen, int *lenp)
+{
+   int l, i;
+   const char *p;
+   char *q, *ret;
+   const char *endp = NULL;
+   
+   if (!start) return NULL;
+   if (inlen >= 0) endp = start + inlen;
+   /* First pass: Count characters */
+   for (l = 0, p = start; ((!endp) || (p < endp)) && (*p); p++)
+     {
+        for (i = 0 ; i < N_ESCAPES ; i ++)
+          {
+             if (*p == escapes[i].value)
+               {
+                  l += strlen(escapes[i].escape);
+                  break;
+               }
+          }
+        if (i == N_ESCAPES) l++;
+     }
+   
+   q = ret = malloc(l + 1);
+   
+   /* Second pass: Change characters */
+  for (p = start; *p; )
+    {
+       for (i = 0; i < N_ESCAPES; i++)
+         {
+            if (*p == escapes[i].value)
+              {
+                 strcpy(q, escapes[i].escape);
+                 q += strlen(escapes[i].escape);
+                 p ++;
+                 break;
+              }
+         }
+       if (i == N_ESCAPES) *q++ = *p++;
+    }
+   *q = 0;
+   
+   if (lenp) *lenp = l;
+   return ret;
+}
+
+
+static Eina_Bool
+_dnd_enter(void *data __UNUSED__, int etype __UNUSED__, void *ev)
+{
+   Ecore_X_Event_Xdnd_Enter *enter = ev;
+   int i;
+
+   /* Skip it */
+   if ((!enter) || (!enter->num_types) || (!enter->types)) return EINA_TRUE;
+
+   cnp_debug("Types\n");
+   savedtypes.ntypes = enter->num_types;
+   if (savedtypes.types) free(savedtypes.types);
+   savedtypes.types = malloc(sizeof(char *) * enter->num_types);
+   if (!savedtypes.types) return EINA_FALSE;
+   
+   for (i = 0; i < enter->num_types; i++)
+     {
+        savedtypes.types[i] = eina_stringshare_add(enter->types[i]);
+        cnp_debug("Type is %s %p %p\n", enter->types[i],
+                  savedtypes.types[i],text_uri);
+        if (savedtypes.types[i] == text_uri)
+          {
+             /* Request it, so we know what it is */
+             cnp_debug("Sending uri request\n");
+             savedtypes.textreq = 1;
+             savedtypes.pi = NULL; /* FIXME: Free? */
+             ecore_x_selection_xdnd_request(enter->win, text_uri);
+          }
+     }
+
+   /* FIXME: Find an object and make it current */
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_dnd_drop(void *data __UNUSED__, int etype __UNUSED__, void *ev)
+{
+   struct _Ecore_X_Event_Xdnd_Drop *drop;
+   Dropable *dropable;
+   Eina_List *l;
+   Ecore_Evas *ee;
+   Ecore_X_Window xwin;
+   Elm_Selection_Data ddata;
+   int x, y, w, h;
+   int i, j;
+
+   drop = ev;
+
+   // check we still have something to drop
+   if (!drops) return EINA_TRUE;
+
+   /* Find any widget in our window; then work out geometry rel to our window */
+   for (l = drops; l; l = l->next)
+     {
+        dropable = l->data;
+        xwin = (Ecore_X_Window)ecore_evas_window_get
+           (ecore_evas_ecore_evas_get(evas_object_evas_get
+                                      (dropable->obj)));
+        if (xwin == drop->win) break;
+     }
+   /* didn't find a window */
+   if (!l) return EINA_TRUE;
+
+   /* Calculate real (widget relative) position */
+   // - window position
+   // - widget position
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(dropable->obj));
+   ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
+   savedtypes.x = drop->position.x - x;
+   savedtypes.y = drop->position.y - y;
+   
+   cnp_debug("Drop position is %d,%d\n", savedtypes.x, savedtypes.y);
+
+   for (; l; l = l->next)
+     {
+        dropable = l->data;
+        evas_object_geometry_get(dropable->obj, &x, &y, &w, &h);
+        if ((savedtypes.x >= x) && (savedtypes.y >= y) &&
+            (savedtypes.x < x + w) && (savedtypes.y < y + h))
+           break; /* found! */
+     }
+   
+   if (!l) return EINA_TRUE; /* didn't find one */
+   
+   evas_object_geometry_get(dropable->obj, &x, &y, NULL, NULL);
+   savedtypes.x -= x;
+   savedtypes.y -= y;
+   
+   /* Find our type from the previous list */
+   for (i = 0; i < CNP_N_ATOMS; i++)
+     {
+       for (j = 0; j < savedtypes.ntypes; j++)
+          {
+             if (!strcmp(savedtypes.types[j], atoms[i].name)) goto found;
+          }
+     }
+   
+   cnp_debug("Didn't find a target\n");
+   return EINA_TRUE;
+   
+found:
+   cnp_debug("Found a target we'd like: %s\n", atoms[i].name);
+   cnp_debug("0x%x\n",xwin);
+   
+   if (i == CNP_ATOM_text_urilist)
+     {
+        cnp_debug("We found a URI... (%scached) %s\n",
+                  savedtypes.pi ? "" : "not ",
+                  savedtypes.pi->file);
+        if (savedtypes.pi)
+          {
+             char *entrytag;
+             static const char *tagstring = "<item absize=240x180 href="
+                                                   "file://%s></item>";
+             ddata.x = savedtypes.x;
+             ddata.y = savedtypes.y;
+
+             /* If it's markup that also supports images */
+             if ((dropable->types & ELM_SEL_FORMAT_MARKUP) &&
+                    (dropable->types & ELM_SEL_FORMAT_IMAGE))
+               {
+                  int len;
+                  ddata.format = ELM_SEL_FORMAT_MARKUP;
+                  pasteimage_provider_set(dropable->obj);
+
+                  pastedimages = eina_list_append(pastedimages, savedtypes.pi);
+                  len = strlen(tagstring) + strlen(savedtypes.pi->file);
+                  entrytag = alloca(len + 1);
+                  snprintf(entrytag, len + 1, tagstring, savedtypes.pi->file);
+                  ddata.data = entrytag;
+                  cnp_debug("Insert %s\n", (char *)ddata.data);
+                  dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
+                  ecore_x_dnd_send_finished();
+                  return EINA_TRUE;
+               }
+             else if (dropable->types & ELM_SEL_FORMAT_IMAGE)
+               {
+                  cnp_debug("Doing image insert (%s)\n", savedtypes.pi->file);
+                  ddata.format = ELM_SEL_FORMAT_IMAGE;
+                  ddata.data = (char *)savedtypes.pi->file;
+                  dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
+                  ecore_x_dnd_send_finished();
+
+                  pasteimage_free(savedtypes.pi);
+                  savedtypes.pi = NULL;
+
+                  return EINA_TRUE;
+               }
+             else
+               {
+                  cnp_debug("Item doesn't support images... passing\n");
+                  pasteimage_free(savedtypes.pi);
+                  return EINA_TRUE;
+               }
+          }
+        else if (savedtypes.textreq)
+          {
+             /* Already asked: Pretend we asked now, and paste immediately when
+              * it comes in */
+             savedtypes.textreq = 0;
+             ecore_x_dnd_send_finished();
+             return EINA_TRUE;
+          }
+     }
+
+   cnp_debug("doing a request then\n");
+   selections[ELM_SEL_XDND].requestwidget = dropable->obj;
+   selections[ELM_SEL_XDND].requestformat = ELM_SEL_FORMAT_MARKUP;
+   selections[ELM_SEL_XDND].active = EINA_TRUE;
+
+   ecore_x_selection_xdnd_request(xwin, atoms[i].name);
+
+   return EINA_TRUE;
+}
+static Eina_Bool
+_dnd_position(void *data __UNUSED__, int etype __UNUSED__, void *ev)
+{
+   struct _Ecore_X_Event_Xdnd_Position *pos;
+   Ecore_X_Rectangle rect;
+
+   pos = ev;
+
+   /* Need to send a status back */
+   /* FIXME: Should check I can drop here */
+   /* FIXME: Should highlight widget */
+   rect.x = pos->position.x - 5;
+   rect.y = pos->position.y - 5;
+   rect.width = 10;
+   rect.height = 10;
+   ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, rect, pos->action);
+
+   return EINA_TRUE;
+}
+
+/**
+ * When dragging this is callback response from the destination.
+ * The important thing we care about: Can we drop; thus update cursor
+ * appropriately.
+ */
+static Eina_Bool
+_dnd_status(void *data __UNUSED__, int etype __UNUSED__, void *ev)
+{
+   struct _Ecore_X_Event_Xdnd_Status *status = ev;
+
+   if (!status) return EINA_TRUE;
+   
+   /* Only thing we care about: will accept */
+   if (status->will_accept)
+     {
+        cnp_debug("Will accept\n");
+     }
+   else
+     { /* Won't accept */
+        cnp_debug("Won't accept accept\n");
+     }
+   return EINA_TRUE;
+}
+
+/**
+ * Add a widget as drop target.
+ */
+Eina_Bool
+elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, void *cbdata)
+{
+   Dropable *drop;
+   Ecore_X_Window xwin;
+   Eina_List *item;
+   int first;
+
+   if (!obj) return EINA_FALSE;
+   if (!_elm_cnp_init_count) _elm_cnp_init();
+
+   /* Is this the first? */
+   first = (!drops) ? 1 : 0;
+
+   EINA_LIST_FOREACH(drops, item, drop)
+     {
+        if (drop->obj == obj)
+          {
+             /* Update: Not a new one */
+             drop->dropcb = dropcb;
+             drop->cbdata = cbdata;
+             drop->types = format;
+             return EINA_TRUE;
+          }
+     }
+
+   /* Create new drop */
+   drop = calloc(1, sizeof(Dropable));
+   if (!drop) return EINA_FALSE;
+   /* FIXME: Check for eina's deranged error method */
+   drops = eina_list_append(drops, drop);
+
+   if (!drops/* || or other error */)
+     {
+        free(drop);
+        return EINA_FALSE;
+     }
+   drop->dropcb = dropcb;
+   drop->cbdata = cbdata;
+   drop->types = format;
+   drop->obj = obj;
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                  /* I love C and varargs */
+                                  (Evas_Object_Event_Cb)elm_drop_target_del,
+                                  obj);
+   /* FIXME: Handle resizes */
+
+   /* If not the first: We're done */
+   if (!first) return EINA_TRUE;
+
+   xwin = (Ecore_X_Window)ecore_evas_window_get
+      (ecore_evas_ecore_evas_get(evas_object_evas_get(obj)));
+   
+   ecore_x_dnd_aware_set(xwin, EINA_TRUE);
+   
+   cnp_debug("Adding drop target calls\n");
+   handler_enter = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
+                                           _dnd_enter, NULL);
+   handler_pos = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
+                                         _dnd_position, NULL);
+   handler_drop = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP,
+                                          _dnd_drop, NULL);
+   
+   return EINA_TRUE;
+}
+
+Eina_Bool
+elm_drop_target_del(Evas_Object *obj)
+{
+   Dropable *drop,*del;
+   Eina_List *item;
+   Ecore_X_Window xwin;
+   
+   del = NULL;
+   EINA_LIST_FOREACH(drops, item, drop)
+     {
+        if (drop->obj == obj)
+          {
+             drops = eina_list_remove_list(drops, item);
+             del = drop;
+             break;
+          }
+     }
+   if (!del) return EINA_FALSE;
+   
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE,
+                                  (Evas_Object_Event_Cb)elm_drop_target_del);
+   free(drop);
+   /* If still drops there: All fine.. continue */
+   if (drops) return EINA_TRUE;
+   
+   cnp_debug("Disabling DND\n");
+   xwin = (Ecore_X_Window)ecore_evas_window_get
+      (ecore_evas_ecore_evas_get(evas_object_evas_get(obj)));
+   ecore_x_dnd_aware_set(xwin, EINA_FALSE);
+   
+   ecore_event_handler_del(handler_pos);
+   ecore_event_handler_del(handler_drop);
+   ecore_event_handler_del(handler_enter);
+   
+   if (savedtypes.pi)
+     {
+        pasteimage_free(savedtypes.pi);
+        savedtypes.pi = NULL;
+     }
+   
+   return EINA_TRUE;
+}
+
+
+static void
+_drag_mouse_up(void *un __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *data __UNUSED__)
+{
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _drag_mouse_up);
+   ecore_x_dnd_drop();
+   if (dragdonecb)
+     {
+        dragdonecb(dragdonecb,selections[ELM_SEL_XDND].widget);
+        dragdonecb = NULL;
+     }
+   if (dragwin)
+     {
+        evas_object_del(dragwin);
+        dragwin = NULL;
+     }
+}
+
+static void
+_drag_move(void *data __UNUSED__, Ecore_X_Xdnd_Position *pos)
+{
+   evas_object_move(dragwin, 
+                    pos->position.x - _dragx, 
+                    pos->position.y - _dragy);
+}
+
+
+Eina_Bool
+elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, void (*dragdone) (void *data, Evas_Object *), void *donecbdata)
+{
+   Ecore_X_Window xwin;
+   Cnp_Selection *sel;
+   Elm_Sel_Type xdnd = ELM_SEL_XDND;
+   Ecore_Evas *ee;
+   int x, y, x2, y2, x3, y3;
+   Evas_Object *icon;
+   int w, h;
+   
+   if (!_elm_cnp_init_count) _elm_cnp_init();
+   
+   xwin = elm_win_xwindow_get(obj);
+
+   cnp_debug("starting drag...\n");
+
+   ecore_x_dnd_type_set(xwin, "text/uri-list", 1);
+   sel = selections + ELM_SEL_XDND;
+   sel->active = 1;
+   sel->widget = obj;
+   sel->format = format;
+   sel->selbuf = data ? strdup(data) : NULL;
+   dragdonecb = dragdone;
+   dragdonedata = donecbdata;
+   
+   ecore_x_dnd_callback_pos_update_set(_drag_move, NULL);
+   ecore_x_dnd_begin(xwin, (unsigned char *)&xdnd, sizeof(Elm_Sel_Type));
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
+                                  _drag_mouse_up, NULL);
+   
+   handler_status = ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS,
+                                            _dnd_status, NULL);
+   
+   dragwin = elm_win_add(NULL, "Elm Drag Object", ELM_WIN_UTILITY);
+   elm_win_override_set(dragwin, 1);
+   
+   /* FIXME: Images only */
+   icon = elm_icon_add(dragwin);
+   elm_icon_file_set(icon, data + 7, NULL); /* 7!? "file://" */
+   elm_win_resize_object_add(dragwin,icon);
+   evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   /* Position subwindow appropriately */
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+   ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
+   evas_object_geometry_get(obj, &x2, &y2, &w, &h);
+   x += x2;
+   y += y2;
+   evas_object_move(dragwin, x, y);
+   evas_object_resize(icon, w, h);
+   evas_object_resize(dragwin, w, h);
+   
+   evas_object_show(icon);
+   evas_object_show(dragwin);
+
+   evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3);
+   _dragx = x3 - x2;
+   _dragy = y3 - y2;
+
+   return EINA_TRUE;
+}
+
+static Tmp_Info *
+elm_cnp_tempfile_create(int size)
+{
+   Tmp_Info *info;
+   const char *tmppath;
+   int len;
+   
+   info = malloc(sizeof(Tmp_Info));
+   if (!info) return NULL;
+   
+   tmppath = getenv("TMP");
+   if (!tmppath) tmppath = P_tmpdir;
+   if (!tmppath) tmppath = "/tmp";
+   len = snprintf(NULL, 0, "%s/%sXXXXXX", tmppath, "elmcnpitem-");
+   if (len < 0)
+     {
+        free(info);
+        return NULL;
+     }
+   len++;
+   info->filename = malloc(len);
+   if (!info->filename)
+     {
+        free(info);
+        return NULL;
+     }
+   snprintf(info->filename,len,"%s/%sXXXXXX", tmppath, "elmcnpitem-");
+   
+   info->fd = mkstemp(info->filename);
+   
+# ifdef __linux__
+     {
+        char *tmp;
+        /* And before someone says anything see POSIX 1003.1-2008 page 400 */
+        long pid;
+        
+        pid = (long)getpid();
+        /* Use pid instead of /proc/self: That way if can be passed around */
+        len = snprintf(NULL,0,"/proc/%li/fd/%i", pid, info->fd);
+        len++;
+        tmp = malloc(len);
+        if (tmp)
+          {
+             snprintf(tmp,len, "/proc/%li/fd/%i", pid, info->fd);
+             unlink(info->filename);
+             free(info->filename);
+             info->filename = tmp;
+          }
+     }
+# endif
+   
+   cnp_debug("filename is %s\n", info->filename);
+   if (size < 1)
+     {
+        /* Set map to NULL and return */
+        info->map = NULL;
+        info->len = 0;
+        return info;
+     }
+   
+   /* Map it in */
+   if (ftruncate(info->fd, size))
+     {
+        perror("ftruncate");
+        info->map = NULL;
+        info->len = 0;
+        return info;
+     }
+   
+   info->map = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, info->fd, 0);
+   if (info->map == MAP_FAILED)
+     {
+        perror("mmap");
+        info->map = NULL;
+        info->len = 0;
+     }
+   
+   return info;
+}
+
+
+static int
+tmpinfo_free(Tmp_Info *info)
+{
+   if (!info) return 0;
+   free(info->filename);
+   free(info);
+   return 0;
+}
+
+#else
+/* Stubs for windows */
+Eina_Bool
+elm_drag_start(Evas_Object *o, Elm_Sel_Format f, const char *d, void (*donecb)(void *, Evas_Object *),void *cbdata)
+{
+   return EINA_FALSE;
+}
+
+Eina_Bool
+elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, void *cbdata)
+{
+   return EINA_FALSE;
+}
+
+Eina_Bool
+elm_drop_target_del(Evas_Object *o)
+{
+   return EINA_TRUE;
+}
+#endif
+
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/src/lib/elm_colorselector.c b/src/lib/elm_colorselector.c
new file mode 100644 (file)
index 0000000..53d4846
--- /dev/null
@@ -0,0 +1,878 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @addtogroup Colorselector Colorselector
+ *
+ * By using colorselector, you can select a color.
+ * Colorselector made a color using HSV/HSB mode.
+ */
+
+#define BASE_STEP 360.0
+#define HUE_STEP 360.0
+#define SAT_STEP 128.0
+#define LIG_STEP 256.0
+#define ALP_STEP 256.0
+
+typedef enum _Button_State
+{
+   BUTTON_RELEASED,
+   L_BUTTON_PRESSED,
+   R_BUTTON_PRESSED
+} Button_State;
+
+typedef enum _Color_Type
+{
+   HUE,
+   SATURATION,
+   LIGHTNESS,
+   ALPHA
+} Color_Type;
+
+typedef struct _Colorselector_Data Colorselector_Data;
+struct _Colorselector_Data
+{
+   Evas_Object *parent;
+   Evas_Object *colorbar;
+   Evas_Object *bar;
+   Evas_Object *lbt;
+   Evas_Object *rbt;
+   Evas_Object *bg_rect;
+   Evas_Object *arrow;
+   Evas_Object *touch_area;
+   Color_Type color_type;
+   Button_State button_state;
+};
+
+typedef struct _Widget_Data Widget_Data;
+struct _Widget_Data
+{
+   Evas_Object *base;
+   Colorselector_Data *cp[4];
+   Evas_Coord _x, _y, _w, _h;
+   int r, g, b, a;
+   int er, eg, eb;
+   int sr, sg, sb;
+   int lr, lg, lb;
+   double h, s, l;
+   Ecore_Timer *lp_timer;
+   Ecore_Timer *mv_timer;
+};
+
+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 _rgb_to_hsl(void *data);
+static void _hsl_to_rgb(void *data);
+static void _color_with_saturation(void *data);
+static void _color_with_lightness(void *data);
+static void _draw_rects(void *data, double x);
+static void _arrow_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _colorbar_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static Eina_Bool _mv_timer(void *data);
+static Eina_Bool _long_press_timer(void *data);
+static void _left_button_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _right_button_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _left_button_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _right_button_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _add_colorbar(Evas_Object *obj);
+static void _set_color(Evas_Object *obj, int r, int g, int b, int a);
+
+#define SIG_CHANGED "changed"
+
+static const Evas_Smart_Cb_Description _signals[] = 
+{
+   {SIG_CHANGED, ""},
+   {NULL, NULL}
+};
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int i = 0;
+
+   if (!wd) return;
+   if (wd->lp_timer) ecore_timer_del(wd->lp_timer);
+   if (wd->mv_timer) ecore_timer_del(wd->mv_timer);
+   for (i = 0; i < 4; i++) free(wd->cp[i]);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int i;
+
+   if ((!wd) || (!wd->base)) return;
+
+   _elm_theme_object_set(obj, wd->base, "colorselector", "bg",
+                        elm_widget_style_get(obj));
+
+   for (i = 0; i < 4; i++)
+     {
+       evas_object_del(wd->cp[i]->colorbar);
+       wd->cp[i]->colorbar = NULL;
+       evas_object_del(wd->cp[i]->bar);
+       wd->cp[i]->bar = NULL;
+       evas_object_del(wd->cp[i]->lbt);
+       wd->cp[i]->lbt = NULL;
+       evas_object_del(wd->cp[i]->rbt);
+       wd->cp[i]->rbt = NULL;
+       if (i != 0)
+         {
+            evas_object_del(wd->cp[i]->bg_rect);
+            wd->cp[i]->bg_rect = NULL;
+         }
+       evas_object_del(wd->cp[i]->arrow);
+       wd->cp[i]->arrow = NULL;
+       evas_object_del(wd->cp[i]->touch_area);
+       wd->cp[i]->touch_area = NULL;
+     }
+
+   _add_colorbar(obj);
+   _sizing_eval(obj);
+}
+
+static void
+_colorselector_set_size_hints(Evas_Object *obj, int timesw, int timesh)
+{
+   Evas_Coord minw = -1, minh = -1;
+
+   elm_coords_finger_size_adjust(timesw, &minw, timesh, &minh);
+   edje_object_size_min_restricted_calc(obj, &minw, &minh,
+                                        minw, minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   int i;
+
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   for (i = 0; i < 4; i++)
+     {
+        if (wd->cp[i]->bg_rect)
+             _colorselector_set_size_hints(wd->cp[i]->bg_rect, 1, 1);
+        _colorselector_set_size_hints(wd->cp[i]->bar, 1, 1);
+        _colorselector_set_size_hints(wd->cp[i]->rbt, 1, 1);
+        _colorselector_set_size_hints(wd->cp[i]->lbt, 1, 1);
+
+        _colorselector_set_size_hints(wd->cp[i]->colorbar, 4, 1);
+
+     }
+
+   elm_coords_finger_size_adjust(4, &minw, 4, &minh);
+   edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_rgb_to_hsl(void *data)
+{
+   Widget_Data *wd = data;
+   double r, g, b;
+   double v, m, vm;
+   double r2, g2, b2;
+
+   r = wd->r;
+   g = wd->g;
+   b = wd->b;
+
+   r /= 255.0;
+   g /= 255.0;
+   b /= 255.0;
+
+   v = (r > g) ? r : g;
+   v = (v > b) ? v : b;
+
+   m = (r < g) ? r : g;
+   m = (m < b) ? m : b;
+
+   wd->h = 0.0;
+   wd->s = 0.0;
+   wd->l = 0.0;
+
+   wd->l = (m + v) / 2.0;
+
+   if (wd->l <= 0.0) return;
+
+   vm = v - m;
+   wd->s = vm;
+
+   if (wd->s > 0.0) wd->s /= (wd->l <= 0.5) ? (v + m) : (2.0 - v - m);
+   else return;
+
+   r2 = (v - r) / vm;
+   g2 = (v - g) / vm;
+   b2 = (v - b) / vm;
+
+   if (r == v) wd->h = (g == m ? 5.0 + b2 : 1.0 - g2);
+   else if (g == v) wd->h = (b == m ? 1.0 + r2 : 3.0 - b2);
+   else wd->h = (r == m ? 3.0 + g2 : 5.0 - r2);
+
+   wd->h *= 60.0;
+}
+
+static void
+_hsl_to_rgb(void *data)
+{
+   Widget_Data *wd = data;
+   double r = 0, g = 0, b = 0;
+   double _h, _s, _l;
+   int i = 0;
+   double sv, vsf, f, p, q, t, v;
+
+   _h = wd->h;
+   _s = wd->s;
+   _l = wd->l;
+
+   if (_s == 0.0) r = g = b = _l;
+   else
+     {
+       if (_h == 360.0) _h = 0.0;
+       _h /= 60.0;
+        
+       v = (_l <= 0.5) ? (_l * (1.0 + _s)) : (_l + _s - (_l * _s));
+       p = _l + _l - v;
+
+       if (v) sv = (v - p) / v;
+       else sv = 0;
+
+       i = (int)_h;
+       f = _h - i;
+
+       vsf = v * sv * f;
+
+       t = p + vsf;
+       q = v - vsf;
+
+       switch (i)
+         {
+          case 0:
+             r = v;
+             g = t;
+             b = p;
+             break;
+          case 1:
+             r = q;
+             g = v;
+             b = p;
+             break;
+          case 2:
+             r = p;
+             g = v;
+             b = t;
+             break;
+          case 3:
+             r = p;
+             g = q;
+             b = v;
+             break;
+          case 4:
+             r = t;
+             g = p;
+             b = v;
+             break;
+          case 5:
+             r = v;
+             g = p;
+             b = q;
+             break;
+         }
+     }
+   i = (int)(r * 255.0);
+   f = (r * 255.0) - i;
+   wd->r = (f <= 0.5) ? i : (i + 1);
+
+   i = (int)(g * 255.0);
+   f = (g * 255.0) - i;
+   wd->g = (f <= 0.5) ? i : (i + 1);
+
+   i = (int)(b * 255.0);
+   f = (b * 255.0) - i;
+   wd->b = (f <= 0.5) ? i : (i + 1);
+}
+
+static void
+_color_with_saturation(void *data)
+{
+   Widget_Data *wd = data;
+
+   if (wd->er > 127) wd->sr = 127 + (int)((double)(wd->er - 127) * wd->s);
+   else wd->sr = 127 - (int)((double)(127 - wd->er) * wd->s);
+   if (wd->eg > 127) wd->sg = 127 + (int)((double)(wd->eg - 127) * wd->s);
+   else wd->sg = 127 - (int)((double)(127 - wd->eg) * wd->s);
+   if (wd->eb > 127) wd->sb = 127 + (int)((double)(wd->eb - 127) * wd->s);
+   else wd->sb = 127 - (int)((double)(127 - wd->eb) * wd->s);
+}
+
+static void
+_color_with_lightness(void *data)
+{
+   Widget_Data *wd = data;
+
+   if (wd->l > 0.5)
+     {
+       wd->lr = wd->er + (int)((double)(255 - wd->er) * (wd->l - 0.5) * 2.0);
+       wd->lg = wd->eg + (int)((double)(255 - wd->eg) * (wd->l - 0.5) * 2.0);
+       wd->lb = wd->eb + (int)((double)(255 - wd->eb) * (wd->l - 0.5) * 2.0);
+     }
+   else if (wd->l < 0.5)
+     {
+       wd->lr = (double)wd->er * wd->l * 2.0;
+       wd->lg = (double)wd->eg * wd->l * 2.0;
+       wd->lb = (double)wd->eb * wd->l * 2.0;
+     }
+   else
+     {
+       wd->lr = wd->er;
+       wd->lg = wd->eg;
+       wd->lb = wd->eb;
+     }
+}
+
+static void
+_draw_rects(void *data, double x)
+{
+   Colorselector_Data *cp = data;
+   Widget_Data *wd = elm_widget_data_get(cp->parent);
+   double one_six = 1.0 / 6.0;
+
+   switch (cp->color_type)
+     {
+     case HUE:
+        wd->h = 360.0 * x;
+        
+        if (x < one_six)
+          {
+             wd->er = 255;
+             wd->eg = (255.0 * x * 6.0);
+             wd->eb = 0;
+          }
+        else if (x < 2 * one_six)
+          {
+             wd->er = 255 - (int)(255.0 * (x - one_six) * 6.0);
+             wd->eg = 255;
+             wd->eb = 0;
+          }
+        else if (x < 3 * one_six)
+          {
+             wd->er = 0;
+             wd->eg = 255;
+             wd->eb = (int)(255.0 * (x - (2.0 * one_six)) * 6.0);
+          }
+        else if (x < 4 * one_six)
+          {
+             wd->er = 0;
+             wd->eg = 255 - (int)(255.0 * (x - (3.0 * one_six)) * 6.0);
+             wd->eb = 255;
+          }
+        else if (x < 5 * one_six)
+          {
+             wd->er = 255.0 * (x - (4.0 * one_six)) * 6.0;
+             wd->eg = 0;
+             wd->eb = 255;
+          }
+        else
+          {
+             wd->er = 255;
+             wd->eg = 0;
+             wd->eb = 255 - (int)(255.0 * (x - (5.0 * one_six)) * 6.0);
+          }
+        
+        evas_object_color_set(wd->cp[0]->arrow, wd->er, wd->eg, wd->eb, 255);
+        evas_object_color_set(wd->cp[1]->bg_rect, wd->er, wd->eg, wd->eb, 255);
+        evas_object_color_set(wd->cp[2]->bg_rect, wd->er, wd->eg, wd->eb, 255);
+        evas_object_color_set(wd->cp[3]->bar, wd->er, wd->eg, wd->eb, 255);
+        
+        _color_with_saturation(wd);
+        evas_object_color_set(wd->cp[1]->arrow, wd->sr, wd->sg, wd->sb, 255);
+        
+        _color_with_lightness(wd);
+        evas_object_color_set(wd->cp[2]->arrow, wd->lr, wd->lg, wd->lb, 255);
+        
+        evas_object_color_set(wd->cp[3]->arrow, 
+                              (wd->er * wd->a) / 255,
+                              (wd->eg * wd->a) / 255, 
+                              (wd->eb * wd->a) / 255,
+                              wd->a);
+        break;
+        
+     case SATURATION:
+        wd->s = 1.0 - x;
+        _color_with_saturation(wd);
+        evas_object_color_set(wd->cp[1]->arrow, wd->sr, wd->sg, wd->sb, 255);
+        break;
+        
+     case LIGHTNESS:
+        wd->l = x;
+        _color_with_lightness(wd);
+        evas_object_color_set(wd->cp[2]->arrow, wd->lr, wd->lg, wd->lb, 255);
+        break;
+        
+     case ALPHA:
+        wd->a = 255.0 * x;
+        evas_object_color_set(wd->cp[3]->arrow, wd->er, wd->eg, wd->eb, wd->a);
+        break;
+        
+     default:
+        break;
+     }
+   _hsl_to_rgb(wd);
+}
+
+static void
+_arrow_cb(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Colorselector_Data *cp = data;
+   double x, y;
+
+   edje_object_part_drag_value_get(obj, "elm.arrow", &x, &y);
+   _draw_rects(data, x);
+   evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
+}
+
+static void
+_colorbar_cb(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Colorselector_Data *cp = data;
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord x, y, w, h;
+   double arrow_x = 0, arrow_y;
+
+   evas_object_geometry_get(cp->bar, &x, &y, &w, &h);
+   edje_object_part_drag_value_get(cp->colorbar, "elm.arrow",
+                                   &arrow_x, &arrow_y);
+   if (w > 0) arrow_x = (double)(ev->output.x - x) / (double)w;
+   if (arrow_x > 1) arrow_x = 1;
+   if (arrow_x < 0) arrow_x = 0;
+   edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", arrow_x, arrow_y);
+   _draw_rects(data, arrow_x);
+   evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
+   evas_event_feed_mouse_cancel(e, 0, NULL);
+   evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, 0, NULL);
+}
+
+static Eina_Bool
+_mv_timer(void *data)
+{
+   Colorselector_Data *cp = data;
+   Widget_Data *wd = elm_widget_data_get(cp->parent);
+   double x, y;
+
+   if (!wd) return EINA_FALSE;
+
+   edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
+   if (cp->button_state == L_BUTTON_PRESSED)
+     {
+       x -= 1.0 / BASE_STEP;
+       if (x < 0.0) x = 0.0;
+       edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
+       _draw_rects(data, x);
+       evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
+       return EINA_TRUE;
+     }
+   else if (cp->button_state == R_BUTTON_PRESSED)
+     {
+       x += 1.0 / BASE_STEP;
+       if (x > 1.0) x = 1.0;
+       edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
+       _draw_rects(data, x);
+       evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
+       return EINA_TRUE;
+     }
+   wd->mv_timer = NULL;
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_long_press_timer(void *data)
+{
+   Colorselector_Data *cp = data;
+   Widget_Data *wd = elm_widget_data_get(cp->parent);
+   
+   if (wd->mv_timer) ecore_timer_del(wd->mv_timer);
+   wd->mv_timer = ecore_timer_add(0.01, _mv_timer, cp);
+
+   wd->lp_timer = NULL;
+   return EINA_FALSE;
+}
+
+static void
+_left_button_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Colorselector_Data *cp = data;
+   Widget_Data *wd = elm_widget_data_get(cp->parent);
+   double x, y;
+
+   edje_object_signal_emit(cp->lbt, "elm,state,left,button,down",
+                          "left_button");
+   edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
+
+   switch(cp->color_type)
+     {
+      case HUE :
+         x -= 1.0 / HUE_STEP;
+         break;
+      case SATURATION :
+         x -= 1.0 / SAT_STEP;
+         break;
+      case LIGHTNESS :
+         x -= 1.0 / LIG_STEP;
+         break;
+      case ALPHA :
+         x -= 1.0 / ALP_STEP;
+         break;
+      default : 
+         break;         
+     }
+
+   if (x < 0.0) x = 0.0;
+
+   edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
+   _draw_rects(data, x);
+   evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
+   cp->button_state = L_BUTTON_PRESSED;
+   if (wd->lp_timer) ecore_timer_del(wd->lp_timer);
+   wd->lp_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press_timer, cp);
+}
+
+static void
+_right_button_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Colorselector_Data *cp = data;
+   Widget_Data *wd = elm_widget_data_get(cp->parent);
+   double x, y;
+
+   edje_object_signal_emit(cp->rbt, "elm,state,right,button,down",
+                          "right_button");
+   edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
+
+   switch(cp->color_type)
+     {
+      case HUE :
+         x += 1.0 / HUE_STEP;
+         break;
+      case SATURATION :
+         x += 1.0 / SAT_STEP;
+         break;
+      case LIGHTNESS :
+         x += 1.0 / LIG_STEP;
+         break;
+      case ALPHA :
+         x += 1.0 / ALP_STEP;
+         break;
+      default : 
+         break;         
+     }
+
+   if (x > 1.0) x = 1.0;
+
+   edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
+   _draw_rects(data, x);
+   evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
+   cp->button_state = R_BUTTON_PRESSED;
+   wd->lp_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press_timer, cp);
+}
+
+static void
+_left_button_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Colorselector_Data *cp = data;
+   Widget_Data *wd = elm_widget_data_get(cp->parent);
+
+   if (wd->lp_timer)
+     {
+       ecore_timer_del(wd->lp_timer);
+       wd->lp_timer = NULL;
+     }
+   if (wd->mv_timer)
+     {
+       ecore_timer_del(wd->mv_timer);
+       wd->mv_timer = NULL;
+     }
+
+   cp->button_state = BUTTON_RELEASED;
+   edje_object_signal_emit(cp->lbt, "elm,state,left,button,up", "left_button");
+}
+
+static void
+_right_button_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Colorselector_Data *cp = data;
+   Widget_Data *wd = elm_widget_data_get(cp->parent);
+
+   if (wd->lp_timer)
+     {
+       ecore_timer_del(wd->lp_timer);
+       wd->lp_timer = NULL;
+     }
+   if (wd->mv_timer)
+     {
+       ecore_timer_del(wd->mv_timer);
+       wd->mv_timer = NULL;
+     }
+
+   cp->button_state = BUTTON_RELEASED;
+   edje_object_signal_emit(cp->rbt, "elm,state,right,button,up",
+                          "right_button");
+}
+
+static void
+_add_colorbar(Evas_Object *obj)
+{
+   char colorbar_name[128];
+   char colorbar_s[128];
+   Widget_Data *wd;
+   Evas *e;
+   int i = 0;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   e = evas_object_evas_get(obj);
+
+   for (i = 0; i < 4; i++)
+     {
+       wd->cp[i] = ELM_NEW(Colorselector_Data);
+       wd->cp[i]->parent = obj;
+        switch(i)
+          {
+           case 0 :
+              wd->cp[i]->color_type = HUE;
+              break;
+           case 1 :
+              wd->cp[i]->color_type = SATURATION;
+              break;
+           case 2 :
+              wd->cp[i]->color_type = LIGHTNESS;
+              break;
+           case 3 :
+              wd->cp[i]->color_type = ALPHA;
+              break;
+           default : 
+              break;         
+          }
+        /* load colorbar area */
+       wd->cp[i]->colorbar = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->cp[i]->colorbar, "colorselector", "base",
+                             "default");
+       snprintf(colorbar_name, sizeof(colorbar_name), "colorbar_%d", i);
+       snprintf(colorbar_s, sizeof(colorbar_s), "elm.colorbar_%d", i);
+       edje_object_signal_callback_add(wd->cp[i]->colorbar, "drag", "*",
+                                       _arrow_cb, wd->cp[i]);
+       edje_object_part_swallow(wd->base, colorbar_s, wd->cp[i]->colorbar);
+       elm_widget_sub_object_add(obj, wd->cp[i]->colorbar);
+
+       /* load colorbar image */
+       wd->cp[i]->bar = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->cp[i]->bar, "colorselector", "image",
+                             colorbar_name);
+       edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar",
+                                 wd->cp[i]->bar);
+       elm_widget_sub_object_add(obj, wd->cp[i]->bar);
+
+       /* provide expanded touch area */
+       wd->cp[i]->touch_area = evas_object_rectangle_add(e);
+       evas_object_color_set(wd->cp[i]->touch_area, 0, 0, 0, 0);
+       edje_object_part_swallow(wd->cp[i]->colorbar, "elm.arrow_bg",
+                                wd->cp[i]->touch_area);
+       evas_object_event_callback_add(wd->cp[i]->touch_area,
+                                      EVAS_CALLBACK_MOUSE_DOWN, _colorbar_cb,
+                                      wd->cp[i]);
+       elm_widget_sub_object_add(obj, wd->cp[i]->touch_area);
+
+       /* load background rectangle of the colorbar. used for
+          changing color of the opacity bar */
+       if ((i == 1) || (i == 2))
+         {
+            wd->cp[i]->bg_rect = evas_object_rectangle_add(e);
+             evas_object_color_set(wd->cp[i]->bg_rect, wd->er, wd->eg, wd->eb,
+                                   255);
+            edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar_bg",
+                                     wd->cp[i]->bg_rect);
+
+            elm_widget_sub_object_add(obj, wd->cp[i]->bg_rect);
+         }
+       if (i == 3)
+          {
+             wd->cp[i]->bg_rect = edje_object_add(e);
+             _elm_theme_object_set(obj, wd->cp[i]->bg_rect, "colorselector",
+                                   "bg_image", colorbar_name);
+             edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar_bg",
+                                      wd->cp[i]->bg_rect);
+             elm_widget_sub_object_add(obj, wd->cp[i]->bg_rect);
+             evas_object_color_set(wd->cp[i]->bar, wd->er, wd->eg, wd->eb, 255);
+          }
+       /* load arrow image, pointing the colorbar */
+       wd->cp[i]->arrow = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->cp[i]->arrow, "colorselector", "image",
+                             "updown");
+       edje_object_part_swallow(wd->cp[i]->colorbar, "elm.arrow_icon",
+                                wd->cp[i]->arrow);
+       elm_widget_sub_object_add(obj, wd->cp[i]->arrow);
+       if (i == 2)
+         evas_object_color_set(wd->cp[i]->arrow, 0, 0, 0, 255);
+       else
+         evas_object_color_set(wd->cp[i]->arrow, wd->er, wd->eg, wd->eb, 255);
+
+       /* load left button */
+       wd->cp[i]->lbt = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->cp[i]->lbt, "colorselector", "button",
+                             "left");
+       evas_object_event_callback_add(wd->cp[i]->lbt, EVAS_CALLBACK_MOUSE_DOWN,
+                                      _left_button_down_cb, wd->cp[i]);
+       evas_object_event_callback_add(wd->cp[i]->lbt, EVAS_CALLBACK_MOUSE_UP,
+                                      _left_button_up_cb, wd->cp[i]);
+       edje_object_part_swallow(wd->cp[i]->colorbar, "elm.l_button",
+                                wd->cp[i]->lbt);
+       elm_widget_sub_object_add(obj, wd->cp[i]->lbt);
+
+       /* load right button */
+       wd->cp[i]->rbt = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->cp[i]->rbt, "colorselector", "button",
+                             "right");
+       evas_object_event_callback_add(wd->cp[i]->rbt, EVAS_CALLBACK_MOUSE_DOWN,
+                                      _right_button_down_cb, wd->cp[i]);
+       evas_object_event_callback_add(wd->cp[i]->rbt, EVAS_CALLBACK_MOUSE_UP,
+                                      _right_button_up_cb, wd->cp[i]);
+       edje_object_part_swallow(wd->cp[i]->colorbar, "elm.r_button",
+                                wd->cp[i]->rbt);
+       elm_widget_sub_object_add(obj, wd->cp[i]->rbt);
+
+     }
+}
+
+static void
+_set_color(Evas_Object *obj, int r, int g, int b, int a)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double x, y;
+
+   wd->r = r;
+   wd->g = g;
+   wd->b = b;
+   wd->a = a;
+
+   _rgb_to_hsl(wd);
+
+   edje_object_part_drag_value_get(wd->cp[0]->colorbar, "elm.arrow", &x, &y);
+   x = wd->h / 360.0;
+   edje_object_part_drag_value_set(wd->cp[0]->colorbar, "elm.arrow", x, y);
+   _draw_rects(wd->cp[0], x);
+
+   edje_object_part_drag_value_get(wd->cp[1]->colorbar, "elm.arrow", &x, &y);
+   x = 1.0 - wd->s;
+   edje_object_part_drag_value_set(wd->cp[1]->colorbar, "elm.arrow", x, y);
+   _draw_rects(wd->cp[1], x);
+
+   edje_object_part_drag_value_get(wd->cp[2]->colorbar, "elm.arrow", &x, &y);
+   x = wd->l;
+   edje_object_part_drag_value_set(wd->cp[2]->colorbar, "elm.arrow", x, y);
+   _draw_rects(wd->cp[2], x);
+
+   edje_object_part_drag_value_get(wd->cp[3]->colorbar, "elm.arrow", &x, &y);
+   x = wd->a / 255.0;
+   edje_object_part_drag_value_set(wd->cp[3]->colorbar, "elm.arrow", x, y);
+   _draw_rects(wd->cp[3], x);
+}
+
+/**
+ * Add a new colorselector to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Colorselector
+ */
+EAPI Evas_Object *
+elm_colorselector_add(Evas_Object *parent)
+{
+   Evas_Object *obj = NULL;
+   Widget_Data *wd = NULL;
+   Evas *e;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "colorselector");
+   elm_widget_type_set(obj, "colorselector");
+   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->base = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->base, "colorselector", "bg", "default");
+   elm_widget_resize_object_set(obj, wd->base);
+
+   wd->er = 255;
+   wd->eg = 0;
+   wd->eb = 0;
+   wd->h = 0.0;
+   wd->s = 1.0;
+   wd->l = 0.0;
+   wd->a = 255;
+
+   _hsl_to_rgb(wd);
+   _add_colorbar(obj);
+   _sizing_eval(obj);
+
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set a color for the colorselector
+ *
+ * @param obj  Colorselector object
+ * @param r    r-value of color
+ * @param g    g-value of color
+ * @param b    b-value of color
+ * @param a    a-value of color
+ *
+ * @ingroup Colorselector
+ */
+EAPI void
+elm_colorselector_color_set(Evas_Object *obj, int r, int g, int b, int a)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   _set_color(obj, r, g, b, a);
+}
+
+/**
+ * Get a color from the colorselector
+ *
+ * @param obj  Colorselector object
+ * @param r    integer pointer for r-value of color
+ * @param g    integer pointer for g-value of color
+ * @param b    integer pointer for b-value of color
+ * @param a    integer pointer for a-value of color
+ *
+ * @ingroup Colorselector
+ */
+EAPI void
+elm_colorselector_color_get(const Evas_Object *obj, int *r, int *g, int *b, int*a)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   if (r) *r = wd->r;
+   if (g) *g = wd->g;
+   if (b) *b = wd->b;
+   if (a) *a = wd->a;
+}
diff --git a/src/lib/elm_config.c b/src/lib/elm_config.c
new file mode 100644 (file)
index 0000000..f0b006e
--- /dev/null
@@ -0,0 +1,1740 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+Elm_Config *_elm_config = NULL;
+char *_elm_profile = NULL;
+static Eet_Data_Descriptor *_config_edd = NULL;
+static Eet_Data_Descriptor *_config_font_overlay_edd = NULL;
+
+static Ecore_Poller *_elm_cache_flush_poller = NULL;
+
+const char *_elm_engines[] = {
+   "software_x11",
+   "fb",
+   "directfb",
+   "software_16_x11",
+   "software_8_x11",
+   "xrender_x11",
+   "opengl_x11",
+   "software_gdi",
+   "software_16_wince_gdi",
+   "sdl",
+   "software_16_sdl",
+   "opengl_sdl",
+   NULL
+};
+
+/* whenever you want to add a new text class support into Elementary,
+   declare it both here and in the (default) theme */
+static const Elm_Text_Class _elm_text_classes[] = {
+   {"button", "Button Labels"},
+   {"label", "Text Labels"},
+   {"entry", "Text Entries"},
+   {"title_bar", "Title Bar"},
+   {"list_item", "List Items"},
+   {"grid_item", "Grid Items"},
+   {"toolbar_item", "Toolbar Items"},
+   {"menu_item", "Menu Items"},
+   {NULL, NULL}
+};
+
+static void        _desc_init(void);
+static void        _desc_shutdown(void);
+static void        _profile_fetch_from_conf(void);
+static void        _config_free(void);
+static void        _config_apply(void);
+static Elm_Config *_config_user_load(void);
+static Elm_Config *_config_system_load(void);
+static void        _config_load(void);
+static void        _config_update(void);
+static void        _env_get(void);
+static size_t      _elm_data_dir_snprintf(char       *dst,
+                                          size_t      size,
+                                          const char *fmt, ...)
+                                          EINA_PRINTF(3, 4);
+static size_t _elm_user_dir_snprintf(char       *dst,
+                                     size_t      size,
+                                     const char *fmt, ...)
+                                     EINA_PRINTF(3, 4);
+
+#define ELM_CONFIG_VAL(edd, type, member, dtype) \
+  EET_DATA_DESCRIPTOR_ADD_BASIC(edd, type, #member, member, dtype)
+#define ELM_CONFIG_LIST(edd, type, member, eddtype) \
+  EET_DATA_DESCRIPTOR_ADD_LIST(edd, type, #member, member, eddtype)
+
+#ifdef HAVE_ELEMENTARY_X
+static Ecore_Event_Handler *_prop_change_handler = NULL;
+static Ecore_X_Window _root_1st = 0;
+#define ATOM_COUNT 22
+static Ecore_X_Atom _atom[ATOM_COUNT];
+static Ecore_X_Atom _atom_config = 0;
+static const char *_atom_names[ATOM_COUNT] =
+{
+   "ENLIGHTENMENT_SCALE",
+   "ENLIGHTENMENT_FINGER_SIZE",
+   "ENLIGHTENMENT_THEME",
+   "ENLIGHTENMENT_PROFILE",
+   "ENLIGHTENMENT_FONT_OVERLAY",
+   "ENLIGHTENMENT_CACHE_FLUSH_INTERVAL",
+   "ENLIGHTENMENT_CACHE_FLUSH_ENABLE",
+   "ENLIGHTENMENT_FONT_CACHE",
+   "ENLIGHTENMENT_IMAGE_CACHE",
+   "ENLIGHTENMENT_EDJE_FILE_CACHE",
+   "ENLIGHTENMENT_EDJE_COLLECTION_CACHE",
+   "ENLIGHTENMENT_THUMBSCROLL_BOUNCE_ENABLE",
+   "ENLIGHTENMENT_THUMBSCROLL_BOUNCE_FRICTION",
+   "ENLIGHTENMENT_THUMBSCROLL_ENABLE",
+   "ENLIGHTENMENT_THUMBSCROLL_THRESHOLD",
+   "ENLIGHTENMENT_THUMBSCROLL_MOMENTUM_THRESHOLD",
+   "ENLIGHTENMENT_THUMBSCROLL_FRICTION",
+   "ENLIGHTENMENT_THUMBSCROLL_BORDER_FRICTION",
+   "ENLIGHTENMENT_THUMBSCROLL_PAGE_SCROLL_FRICTION",
+   "ENLIGHTENMENT_THUMBSCROLL_BRING_IN_SCROLL_FRICTION",
+   "ENLIGHTENMENT_THUMBSCROLL_ZOOM_FRICTION",
+   "ENLIGHTENMENT_CONFIG"
+};
+#define ATOM_E_SCALE                                0
+#define ATOM_E_FINGER_SIZE                          1
+#define ATOM_E_THEME                                2
+#define ATOM_E_PROFILE                              3
+#define ATOM_E_FONT_OVERLAY                         4
+#define ATOM_E_CACHE_FLUSH_INTERVAL                 5
+#define ATOM_E_CACHE_FLUSH_ENABLE                   6
+#define ATOM_E_FONT_CACHE                           7
+#define ATOM_E_IMAGE_CACHE                          8
+#define ATOM_E_EDJE_FILE_CACHE                      9
+#define ATOM_E_EDJE_COLLECTION_CACHE                10
+#define ATOM_E_THUMBSCROLL_BOUNCE_ENABLE            11
+#define ATOM_E_THUMBSCROLL_BOUNCE_FRICTION          12
+#define ATOM_E_THUMBSCROLL_ENABLE                   13
+#define ATOM_E_THUMBSCROLL_THRESHOLD                14
+#define ATOM_E_THUMBSCROLL_MOMENTUM_THRESHOLD       15
+#define ATOM_E_THUMBSCROLL_FRICTION                 16
+#define ATOM_E_THUMBSCROLL_BORDER_FRICTION          17
+#define ATOM_E_THUMBSCROLL_PAGE_SCROLL_FRICTION     18
+#define ATOM_E_THUMBSCROLL_BRING_IN_SCROLL_FRICTION 19
+#define ATOM_E_THUMBSCROLL_ZOOM_FRICTION            20
+#define ATOM_E_CONFIG                               21
+
+static Eina_Bool _prop_config_get(void);
+static Eina_Bool _prop_change(void *data  __UNUSED__,
+                              int ev_type __UNUSED__,
+                              void       *ev);
+
+static Eina_Bool
+_prop_config_get(void)
+{
+   int size = 0;
+   Ecore_X_Atom atom;
+   char buf[512];
+   unsigned char *data = NULL;
+   Elm_Config *config_data;
+
+   snprintf(buf, sizeof(buf), "ENLIGHTENMENT_CONFIG_%s", _elm_profile);
+   atom = ecore_x_atom_get(buf);
+   _atom_config = atom;
+   if (!ecore_x_window_prop_property_get(_root_1st,
+                                         atom, _atom[ATOM_E_CONFIG],
+                                         8, &data, &size))
+     {
+        if (!ecore_x_window_prop_property_get(_root_1st,
+                                              _atom[ATOM_E_CONFIG],
+                                              _atom[ATOM_E_CONFIG],
+                                              8, &data, &size))
+          return EINA_FALSE;
+        else
+          _atom_config = _atom[ATOM_E_CONFIG];
+     }
+   else
+     _atom_config = atom;
+   if (size < 1)
+     {
+        free(data);
+        return EINA_FALSE;
+     }
+   config_data = eet_data_descriptor_decode(_config_edd, data, size);
+   free(data);
+   if (!config_data) return EINA_FALSE;
+
+   /* What do we do on version mismatch when someone changes the
+    * config in the rootwindow? */
+   /* Most obvious case, new version and we are still linked to
+    * whatever was there before, we just ignore until user restarts us */
+   if (config_data->config_version > ELM_CONFIG_VERSION)
+     return EINA_TRUE;
+   /* What in the case the version is older? Do we even support those
+    * cases or we only check for equality above? */
+
+   _config_free();
+   _elm_config = config_data;
+   _config_apply();
+   _elm_config_font_overlay_apply();
+   _elm_rescale();
+   _elm_recache();
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_prop_change(void *data  __UNUSED__,
+             int ev_type __UNUSED__,
+             void       *ev)
+{
+   Ecore_X_Event_Window_Property *event = ev;
+
+   if (event->win == _root_1st)
+     {
+        if (event->atom == _atom[ATOM_E_SCALE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  double pscale;
+
+                  pscale = _elm_config->scale;
+                  if (val > 0) _elm_config->scale = (double)val / 1000.0;
+                  if (pscale != _elm_config->scale)
+                    {
+                       _elm_rescale();
+                       _elm_recache();
+                    }
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_FINGER_SIZE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  int pfinger_size;
+
+                  pfinger_size = _elm_config->finger_size;
+                  _elm_config->finger_size = val;
+                  if (pfinger_size != _elm_config->finger_size)
+                    {
+                       _elm_rescale();
+                       _elm_recache();
+                    }
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THEME])
+          {
+             char *val = NULL;
+
+             val = ecore_x_window_prop_string_get(event->win,
+                                                  event->atom);
+             eina_stringshare_replace(&_elm_config->theme, val);
+             if (val)
+               {
+                  _elm_theme_parse(NULL, val);
+                  free(val);
+                  _elm_rescale();
+                  _elm_recache();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_PROFILE])
+          {
+             char *val = NULL;
+
+             val = ecore_x_window_prop_string_get(event->win,
+                                                  event->atom);
+             if (val)
+               {
+                  int changed = 0;
+
+                  if (_elm_profile)
+                    {
+                       if (strcmp(_elm_profile, val)) changed = 1;
+                       free(_elm_profile);
+                    }
+                  _elm_profile = val;
+                  if (changed)
+                    {
+                       if (!_prop_config_get())
+                         {
+                            _config_free();
+                            _config_load();
+                            _config_apply();
+                            _elm_config_font_overlay_apply();
+                            _elm_rescale();
+                         }
+                    }
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_FONT_OVERLAY])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  _config_free();
+                  _config_load();
+                  _config_apply();
+                  _elm_config_font_overlay_apply();
+                  _elm_rescale();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_CACHE_FLUSH_INTERVAL])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  int cache_flush_interval;
+
+                  cache_flush_interval = _elm_config->cache_flush_poll_interval;
+                  _elm_config->cache_flush_poll_interval = val;
+                  if (cache_flush_interval !=
+                      _elm_config->cache_flush_poll_interval)
+                    _elm_recache();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_CACHE_FLUSH_ENABLE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  _elm_config->cache_flush_enable = !!val;
+                  _elm_recache();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_FONT_CACHE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  int font_cache;
+
+                  font_cache = _elm_config->font_cache;
+                  _elm_config->font_cache = val;
+                  if (font_cache != _elm_config->font_cache)
+                    _elm_recache();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_IMAGE_CACHE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  int image_cache;
+
+                  image_cache = _elm_config->image_cache;
+                  _elm_config->image_cache = val;
+                  if (image_cache != _elm_config->image_cache)
+                    _elm_recache();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_EDJE_FILE_CACHE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  int edje_file_cache;
+
+                  edje_file_cache = _elm_config->edje_cache;
+                  _elm_config->edje_cache = val;
+                  if (edje_file_cache != _elm_config->edje_cache)
+                    _elm_recache();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_EDJE_COLLECTION_CACHE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  int edje_collection_cache;
+
+                  edje_collection_cache = _elm_config->edje_collection_cache;
+                  _elm_config->edje_collection_cache = val;
+                  if (edje_collection_cache !=
+                      _elm_config->edje_collection_cache)
+                    _elm_recache();
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_BOUNCE_ENABLE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  _elm_config->thumbscroll_bounce_enable = !!val;
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_BOUNCE_FRICTION])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    _elm_config->thumbscroll_bounce_friction =
+                      (double)val / 1000.0;
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_ENABLE])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  _elm_config->thumbscroll_enable = !!val;
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_THRESHOLD])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0) _elm_config->thumbscroll_threshold = val;
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_MOMENTUM_THRESHOLD])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    _elm_config->thumbscroll_momentum_threshold =
+                      (double)val / 1000.0;
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_FRICTION])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    _elm_config->thumbscroll_friction = (double)val / 1000.0;
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_BORDER_FRICTION])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    _elm_config->thumbscroll_border_friction =
+                      (double)val / 1000.0;
+               }
+          }
+        else if (event->atom == _atom[ATOM_E_THUMBSCROLL_PAGE_SCROLL_FRICTION])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    _elm_config->page_scroll_friction =
+                      (double)val / 1000.0;
+               }
+          }
+        else if (event->atom ==
+                 _atom[ATOM_E_THUMBSCROLL_BRING_IN_SCROLL_FRICTION])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    _elm_config->bring_in_scroll_friction =
+                      (double)val / 1000.0;
+               }
+          }
+        else if (event->atom ==
+                 _atom[ATOM_E_THUMBSCROLL_ZOOM_FRICTION])
+          {
+             unsigned int val = 1000;
+
+             if (ecore_x_window_prop_card32_get(event->win,
+                                                event->atom,
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    _elm_config->zoom_friction = (double)val / 1000.0;
+               }
+          }
+        else if (((_atom_config > 0) && (event->atom == _atom_config)) ||
+                 (event->atom == _atom[ATOM_E_CONFIG]))
+          {
+             _prop_config_get();
+          }
+     }
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+#endif
+
+static void
+_desc_init(void)
+{
+   Eet_Data_Descriptor_Class eddc;
+
+   EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Config);
+   eddc.func.str_direct_alloc = NULL;
+   eddc.func.str_direct_free = NULL;
+
+   _config_edd = eet_data_descriptor_file_new(&eddc);
+   if (!_config_edd)
+     {
+        printf("EEEK! eet_data_descriptor_file_new() failed\n");
+        return;
+     }
+
+   memset(&eddc, 0, sizeof(eddc)); /* just in case... */
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Font_Overlay);
+   eddc.func.str_direct_alloc = NULL;
+   eddc.func.str_direct_free = NULL;
+
+   _config_font_overlay_edd = eet_data_descriptor_stream_new(&eddc);
+   if (!_config_font_overlay_edd)
+     {
+        printf("EEEK! eet_data_descriptor_stream_new() failed\n");
+        eet_data_descriptor_free(_config_edd);
+        return;
+     }
+#define T_INT    EET_T_INT
+#define T_DOUBLE EET_T_DOUBLE
+#define T_STRING EET_T_STRING
+#define T_UCHAR  EET_T_UCHAR
+
+#define T        Elm_Font_Overlay
+#define D        _config_font_overlay_edd
+   ELM_CONFIG_VAL(D, T, text_class, EET_T_STRING);
+   ELM_CONFIG_VAL(D, T, font, EET_T_STRING);
+   ELM_CONFIG_VAL(D, T, size, EET_T_INT);
+#undef T
+#undef D
+
+#define T Elm_Config
+#define D _config_edd
+   ELM_CONFIG_VAL(D, T, config_version, T_INT);
+   ELM_CONFIG_VAL(D, T, engine, T_STRING);
+   ELM_CONFIG_VAL(D, T, thumbscroll_enable, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, thumbscroll_threshold, T_INT);
+   ELM_CONFIG_VAL(D, T, thumbscroll_momentum_threshold, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, thumbscroll_friction, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, thumbscroll_bounce_friction, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, thumbscroll_border_friction, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, page_scroll_friction, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, bring_in_scroll_friction, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, zoom_friction, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, thumbscroll_bounce_enable, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, scale, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, bgpixmap, T_INT);
+   ELM_CONFIG_VAL(D, T, compositing, T_INT);
+   /* EET_DATA_DESCRIPTOR_ADD_LIST(D, T, "font_dirs", font_dirs, sub_edd); */
+   ELM_CONFIG_LIST(D, T, font_overlays, _config_font_overlay_edd);
+   ELM_CONFIG_VAL(D, T, font_hinting, T_INT);
+   ELM_CONFIG_VAL(D, T, cache_flush_poll_interval, T_INT);
+   ELM_CONFIG_VAL(D, T, cache_flush_enable, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, image_cache, T_INT);
+   ELM_CONFIG_VAL(D, T, font_cache, T_INT);
+   ELM_CONFIG_VAL(D, T, edje_cache, T_INT);
+   ELM_CONFIG_VAL(D, T, edje_collection_cache, T_INT);
+   ELM_CONFIG_VAL(D, T, finger_size, T_INT);
+   ELM_CONFIG_VAL(D, T, fps, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, theme, T_STRING);
+   ELM_CONFIG_VAL(D, T, modules, T_STRING);
+   ELM_CONFIG_VAL(D, T, tooltip_delay, T_DOUBLE);
+   ELM_CONFIG_VAL(D, T, cursor_engine_only, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, focus_highlight_enable, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, focus_highlight_animate, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, toolbar_shrink_mode, T_INT);
+   ELM_CONFIG_VAL(D, T, fileselector_expand_enable, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, inwin_dialogs_enable, T_UCHAR);
+   ELM_CONFIG_VAL(D, T, icon_size, T_INT);
+   ELM_CONFIG_VAL(D, T, longpress_timeout, T_DOUBLE);
+#undef T
+#undef D
+#undef T_INT
+#undef T_DOUBLE
+#undef T_STRING
+#undef T_UCHAR
+}
+
+static void
+_desc_shutdown(void)
+{
+   if (_config_edd)
+     {
+        eet_data_descriptor_free(_config_edd);
+        _config_edd = NULL;
+     }
+
+   if (_config_font_overlay_edd)
+     {
+        eet_data_descriptor_free(_config_font_overlay_edd);
+        _config_font_overlay_edd = NULL;
+     }
+}
+
+static int
+_sort_files_cb(const void *f1,
+               const void *f2)
+{
+   return strcmp(f1, f2);
+}
+
+const char *
+_elm_config_current_profile_get(void)
+{
+   return _elm_profile;
+}
+
+static size_t
+_elm_data_dir_snprintf(char       *dst,
+                       size_t      size,
+                       const char *fmt,
+                       ...)
+{
+   size_t data_dir_len, off;
+   va_list ap;
+
+   data_dir_len = eina_strlcpy(dst, _elm_data_dir, size);
+
+   off = data_dir_len + 1;
+   if (off >= size)
+     goto end;
+
+   va_start(ap, fmt);
+   dst[data_dir_len] = '/';
+
+   off = off + vsnprintf(dst + off, size - off, fmt, ap);
+   va_end(ap);
+
+end:
+   return off;
+}
+
+static size_t
+_elm_user_dir_snprintf(char       *dst,
+                       size_t      size,
+                       const char *fmt,
+                       ...)
+{
+   const char *home;
+   size_t user_dir_len, off;
+   va_list ap;
+
+   home = getenv("HOME");
+   if (!home)
+     home = "/";
+
+   user_dir_len = eina_str_join_len(dst, size, '/', home, strlen(home),
+                                    ".elementary", sizeof(".elementary") - 1);
+
+   off = user_dir_len + 1;
+   if (off >= size)
+     goto end;
+
+   va_start(ap, fmt);
+   dst[user_dir_len] = '/';
+
+   off = off + vsnprintf(dst + off, size - off, fmt, ap);
+   va_end(ap);
+
+end:
+   return off;
+}
+
+const char *
+_elm_config_profile_dir_get(const char *prof,
+                            Eina_Bool   is_user)
+{
+   char buf[PATH_MAX];
+
+   if (!is_user)
+     goto not_user;
+
+   _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s", prof);
+
+   if (ecore_file_is_dir(buf))
+     return strdup(buf);
+
+   return NULL;
+
+not_user:
+   snprintf(buf, sizeof(buf), "%s/config/%s", _elm_data_dir, prof);
+
+   if (ecore_file_is_dir(buf))
+     return strdup(buf);
+
+   return NULL;
+}
+
+Eina_List *
+_elm_config_font_overlays_list(void)
+{
+   return _elm_config->font_overlays;
+}
+
+void
+_elm_config_font_overlay_set(const char    *text_class,
+                             const char    *font,
+                             Evas_Font_Size size)
+{
+   Elm_Font_Overlay *efd;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
+     {
+        if (strcmp(efd->text_class, text_class))
+          continue;
+
+        if (efd->font) eina_stringshare_del(efd->font);
+        efd->font = eina_stringshare_add(font);
+        efd->size = size;
+        _elm_config->font_overlays =
+          eina_list_promote_list(_elm_config->font_overlays, l);
+        return;
+     }
+
+   /* the text class doesn't exist */
+   efd = calloc(1, sizeof(Elm_Font_Overlay));
+   efd->text_class = eina_stringshare_add(text_class);
+   efd->font = eina_stringshare_add(font);
+   efd->size = size;
+
+   _elm_config->font_overlays = eina_list_prepend(_elm_config->font_overlays,
+                                                  efd);
+}
+
+void
+_elm_config_font_overlay_remove(const char *text_class)
+{
+   Elm_Font_Overlay *efd;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
+     {
+        if (strcmp(efd->text_class, text_class))
+          continue;
+
+        _elm_config->font_overlays =
+          eina_list_remove_list(_elm_config->font_overlays, l);
+        if (efd->text_class) eina_stringshare_del(efd->text_class);
+        if (efd->font) eina_stringshare_del(efd->font);
+        free(efd);
+
+        return;
+     }
+}
+
+void
+_elm_config_font_overlay_apply(void)
+{
+   Elm_Font_Overlay *efd;
+   Eina_List *l;
+   int i;
+
+   for (i = 0; _elm_text_classes[i].desc; i++)
+     edje_text_class_del(_elm_text_classes[i].name);
+
+   EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
+     edje_text_class_set(efd->text_class, efd->font, efd->size);
+}
+
+Eina_List *
+_elm_config_text_classes_get(void)
+{
+   Eina_List *ret = NULL;
+   int i;
+
+   for (i = 0; _elm_text_classes[i].desc; i++)
+     {
+        Elm_Text_Class *tc;
+        tc = malloc(sizeof(*tc));
+
+        *tc = _elm_text_classes[i];
+
+        ret = eina_list_append(ret, tc);
+     }
+
+   return ret;
+}
+
+void
+_elm_config_text_classes_free(Eina_List *l)
+{
+   Elm_Text_Class *tc;
+
+   EINA_LIST_FREE(l, tc)
+     free(tc);
+}
+
+Eina_List *
+_elm_config_profiles_list(void)
+{
+   const Eina_File_Direct_Info *info;
+   Eina_List *flist = NULL;
+   Eina_Iterator *file_it;
+   char buf[PATH_MAX];
+   const char *dir;
+   size_t len;
+
+   len = _elm_user_dir_snprintf(buf, sizeof(buf), "config");
+
+   file_it = eina_file_direct_ls(buf);
+   if (!file_it)
+     goto sys;
+
+   buf[len] = '/';
+   len++;
+
+   len = sizeof(buf) - len;
+
+   EINA_ITERATOR_FOREACH(file_it, info)
+     {
+        if (info->name_length >= len)
+          continue;
+
+        if (info->type == EINA_FILE_DIR)
+          {
+             flist =
+               eina_list_sorted_insert(flist, _sort_files_cb,
+                                       eina_stringshare_add(info->path +
+                                                            info->name_start));
+          }
+     }
+
+   eina_iterator_free(file_it);
+
+sys:
+   len = eina_str_join_len(buf, sizeof(buf), '/', _elm_data_dir,
+                           strlen(_elm_data_dir), "config",
+                           sizeof("config") - 1);
+
+   file_it = eina_file_direct_ls(buf);
+   if (!file_it)
+     goto list_free;
+
+   buf[len] = '/';
+   len++;
+
+   len = sizeof(buf) - len;
+   EINA_ITERATOR_FOREACH(file_it, info)
+     {
+        if (info->name_length >= len)
+          continue;
+
+        switch (info->type)
+          {
+           case EINA_FILE_DIR:
+           {
+              const Eina_List *l;
+              const char *tmp;
+
+              EINA_LIST_FOREACH(flist, l, tmp)
+                if (!strcmp(info->path + info->name_start, tmp))
+                  break;
+
+              if (!l)
+                flist =
+                  eina_list_sorted_insert(flist, _sort_files_cb,
+                                          eina_stringshare_add(info->path +
+                                                               info->name_start));
+           }
+           break;
+
+           default:
+             continue;
+          }
+     }
+   return flist;
+
+   eina_iterator_free(file_it);
+
+list_free:
+   EINA_LIST_FREE(flist, dir)
+     eina_stringshare_del(dir);
+
+   return NULL;
+}
+
+static void
+_profile_fetch_from_conf(void)
+{
+   char buf[PATH_MAX], *p, *s;
+   Eet_File *ef = NULL;
+   int len = 0;
+
+   _elm_profile = strdup("default");
+
+   // if env var - use profile without question
+   s = getenv("ELM_PROFILE");
+   if (s)
+     {
+        free(_elm_profile);
+        _elm_profile = strdup(s);
+        return;
+     }
+
+   // user profile
+   _elm_user_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
+   ef = eet_open(buf, EET_FILE_MODE_READ);
+   if (ef)
+     {
+        p = eet_read(ef, "config", &len);
+        if (p)
+          {
+             free(_elm_profile);
+             _elm_profile = malloc(len + 1);
+             memcpy(_elm_profile, p, len);
+             _elm_profile[len] = 0;
+             free(p);
+          }
+        eet_close(ef);
+        if (!p) ef = NULL;
+     }
+   if (ef) return;
+
+   // system profile
+   _elm_data_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
+   ef = eet_open(buf, EET_FILE_MODE_READ);
+   if (ef)
+     {
+        p = eet_read(ef, "config", &len);
+        if (p)
+          {
+             free(_elm_profile);
+             _elm_profile = malloc(len + 1);
+             memcpy(_elm_profile, p, len);
+             _elm_profile[len] = 0;
+             free(p);
+          }
+        eet_close(ef);
+     }
+}
+
+static void
+_config_free(void)
+{
+   Elm_Font_Overlay *fo;
+   const char *fontdir;
+
+   if (!_elm_config) return;
+   EINA_LIST_FREE(_elm_config->font_dirs, fontdir)
+     {
+        eina_stringshare_del(fontdir);
+     }
+   if (_elm_config->engine) eina_stringshare_del(_elm_config->engine);
+   EINA_LIST_FREE(_elm_config->font_overlays, fo)
+     {
+        if (fo->text_class) eina_stringshare_del(fo->text_class);
+        if (fo->font) eina_stringshare_del(fo->font);
+        free(fo);
+     }
+   if (_elm_config->theme) eina_stringshare_del(_elm_config->theme);
+   if (_elm_config->modules) eina_stringshare_del(_elm_config->modules);
+   free(_elm_config);
+   _elm_config = NULL;
+}
+
+static void
+_config_apply(void)
+{
+   _elm_theme_parse(NULL, _elm_config->theme);
+   ecore_animator_frametime_set(1.0 / _elm_config->fps);
+}
+
+static void
+_config_sub_apply(void)
+{
+   edje_frametime_set(1.0 / _elm_config->fps);
+   edje_scale_set(_elm_config->scale);
+   if (_elm_config->modules) _elm_module_parse(_elm_config->modules);
+}
+
+static Eina_Bool
+_elm_cache_flush_cb(void *data __UNUSED__)
+{
+   elm_all_flush();
+   return ECORE_CALLBACK_RENEW;
+}
+
+/* kind of abusing this call right now -- shared between all of those
+ * properties -- but they are not meant to be called that periodically
+ * anyway */
+void
+_elm_recache(void)
+{
+   Eina_List *l;
+   Evas_Object *win;
+
+   elm_all_flush();
+
+   EINA_LIST_FOREACH(_elm_win_list, l, win)
+     {
+        Evas *e = evas_object_evas_get(win);
+        evas_image_cache_set(e, _elm_config->image_cache);
+        evas_font_cache_set(e, _elm_config->font_cache);
+     }
+   edje_file_cache_set(_elm_config->edje_cache);
+   edje_collection_cache_set(_elm_config->edje_collection_cache);
+
+   if (_elm_cache_flush_poller)
+     {
+        ecore_poller_del(_elm_cache_flush_poller);
+        _elm_cache_flush_poller = NULL;
+     }
+   if (_elm_config->cache_flush_enable)
+     {
+        if (_elm_config->cache_flush_poll_interval > 0)
+          {
+             _elm_cache_flush_poller =
+                ecore_poller_add(ECORE_POLLER_CORE,
+                                 _elm_config->cache_flush_poll_interval,
+                                 _elm_cache_flush_cb, NULL);
+          }
+     }
+}
+
+static Elm_Config *
+_config_user_load(void)
+{
+   Elm_Config *cfg = NULL;
+   Eet_File *ef;
+   char buf[PATH_MAX];
+
+   _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s/base.cfg",
+                          _elm_profile);
+
+   ef = eet_open(buf, EET_FILE_MODE_READ);
+   if (ef)
+     {
+        cfg = eet_data_read(ef, _config_edd, "config");
+        eet_close(ef);
+     }
+   return cfg;
+}
+
+static Elm_Config *
+_config_system_load(void)
+{
+   Elm_Config *cfg = NULL;
+   Eet_File *ef;
+   char buf[PATH_MAX];
+
+   _elm_data_dir_snprintf(buf, sizeof(buf), "config/%s/base.cfg",
+                          _elm_profile);
+
+   ef = eet_open(buf, EET_FILE_MODE_READ);
+   if (ef)
+     {
+        cfg = eet_data_read(ef, _config_edd, "config");
+        eet_close(ef);
+     }
+   return cfg;
+}
+
+static void
+_config_load(void)
+{
+   _elm_config = _config_user_load();
+   if (_elm_config)
+     {
+        if (_elm_config->config_version < ELM_CONFIG_VERSION)
+          _config_update();
+        return;
+     }
+
+   /* no user config, fallback for system. No need to check version for
+    * this one, if it's not the right one, someone screwed up at the time
+    * of installing it */
+   _elm_config = _config_system_load();
+   if (_elm_config) return;
+   /* FIXME: config load could have failed because of a non-existent
+    * profile. Fallback to default before moving on */
+
+   // config load fail - defaults
+   /* XXX: do these make sense? Only if it's valid to install the lib
+    * without the config, but do we want that? */
+   _elm_config = ELM_NEW(Elm_Config);
+   _elm_config->config_version = ELM_CONFIG_VERSION;
+   _elm_config->engine = eina_stringshare_add("software_x11");
+   _elm_config->thumbscroll_enable = EINA_TRUE;
+   _elm_config->thumbscroll_threshold = 24;
+   _elm_config->thumbscroll_momentum_threshold = 100.0;
+   _elm_config->thumbscroll_friction = 1.0;
+   _elm_config->thumbscroll_bounce_friction = 0.5;
+   _elm_config->thumbscroll_bounce_enable = EINA_TRUE;
+   _elm_config->page_scroll_friction = 0.5;
+   _elm_config->bring_in_scroll_friction = 0.5;
+   _elm_config->zoom_friction = 0.5;
+   _elm_config->thumbscroll_border_friction = 0.5;
+   _elm_config->scale = 1.0;
+   _elm_config->bgpixmap = 0;
+   _elm_config->compositing = 1;
+   _elm_config->font_hinting = 2;
+   _elm_config->cache_flush_poll_interval = 512;
+   _elm_config->cache_flush_enable = EINA_TRUE;
+   _elm_config->font_dirs = NULL;
+   _elm_config->image_cache = 4096;
+   _elm_config->font_cache = 512;
+   _elm_config->edje_cache = 32;
+   _elm_config->edje_collection_cache = 64;
+   _elm_config->finger_size = 40;
+   _elm_config->fps = 60.0;
+   _elm_config->theme = eina_stringshare_add("default");
+   _elm_config->modules = NULL;
+   _elm_config->tooltip_delay = 1.0;
+   _elm_config->cursor_engine_only = EINA_TRUE;
+   _elm_config->focus_highlight_enable = EINA_FALSE;
+   _elm_config->focus_highlight_animate = EINA_TRUE;
+   _elm_config->toolbar_shrink_mode = 2;
+   _elm_config->fileselector_expand_enable = EINA_FALSE;
+   _elm_config->inwin_dialogs_enable = EINA_FALSE;
+   _elm_config->icon_size = 32;
+   _elm_config->longpress_timeout = 1.0;
+}
+
+static const char *
+_elm_config_eet_close_error_get(Eet_File *ef,
+                                char     *file)
+{
+   Eet_Error err;
+   const char *erstr = NULL;
+
+   err = eet_close(ef);
+   switch (err)
+     {
+      case EET_ERROR_WRITE_ERROR:
+        erstr = "An error occurred while saving Elementary's "
+                "settings to disk. The error could not be "
+                "deterimined. The file where the error occurred was: "
+                "%s. This file has been deleted to avoid corrupt data.";
+        break;
+
+      case EET_ERROR_WRITE_ERROR_FILE_TOO_BIG:
+        erstr = "Elementary's settings files are too big "
+                "for the file system they are being saved to. "
+                "This error is very strange as the files should "
+                "be extremely small. Please check the settings "
+                "for your home directory. "
+                "The file where the error occurred was: %s ."
+                "This file has been deleted to avoid corrupt data.";
+        break;
+
+      case EET_ERROR_WRITE_ERROR_IO_ERROR:
+        erstr = "An output error occurred when writing the settings "
+                "files for Elementary. Your disk is having troubles "
+                "and possibly needs replacement. "
+                "The file where the error occurred was: %s ."
+                "This file has been deleted to avoid corrupt data.";
+        break;
+
+      case EET_ERROR_WRITE_ERROR_OUT_OF_SPACE:
+        erstr = "Elementary cannot write its settings file "
+                "because it ran out of space to write the file. "
+                "You have either run out of disk space or have "
+                "gone over your quota limit. "
+                "The file where the error occurred was: %s ."
+                "This file has been deleted to avoid corrupt data.";
+        break;
+
+      case EET_ERROR_WRITE_ERROR_FILE_CLOSED:
+        erstr = "Elementary unexpectedly had the settings file "
+                "it was writing closed on it. This is very unusual. "
+                "The file where the error occurred was: %s "
+                "This file has been deleted to avoid corrupt data.";
+        break;
+
+      default:
+        break;
+     }
+   if (erstr)
+     {
+        /* delete any partially-written file */
+         ecore_file_unlink(file);
+         return strdup(erstr);
+     }
+
+   return NULL;
+}
+
+static Eina_Bool
+_elm_config_profile_save(void)
+{
+   char buf[4096], buf2[4096];
+   int ok = 0, ret;
+   const char *err;
+   Eet_File *ef;
+   size_t len;
+
+   len = _elm_user_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
+   if (len + 1 >= sizeof(buf))
+     return EINA_FALSE;
+
+   len = _elm_user_dir_snprintf(buf2, sizeof(buf2), "config/profile.cfg.tmp");
+   if (len + 1 >= sizeof(buf2))
+     return EINA_FALSE;
+
+   ef = eet_open(buf2, EET_FILE_MODE_WRITE);
+   if (!ef)
+     return EINA_FALSE;
+
+   ok = eet_write(ef, "config", _elm_profile, strlen(_elm_profile), 0);
+   if (!ok)
+     goto err;
+
+   err = _elm_config_eet_close_error_get(ef, buf2);
+   if (err)
+     {
+        ERR("%s", err);
+        free((void *)err);
+        goto err;
+     }
+
+   ret = ecore_file_mv(buf2, buf);
+   if (!ret)
+     {
+        ERR("Error saving Elementary's configuration file");
+        goto err;
+     }
+
+   ecore_file_unlink(buf2);
+   return EINA_TRUE;
+
+err:
+   ecore_file_unlink(buf2);
+   return EINA_FALSE;
+}
+
+Eina_Bool
+_elm_config_save(void)
+{
+   char buf[4096], buf2[4096];
+   int ok = 0, ret;
+   const char *err;
+   Eet_File *ef;
+   size_t len;
+
+   len = _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s", _elm_profile);
+   if (len + 1 >= sizeof(buf))
+     return EINA_FALSE;
+
+   ok = ecore_file_mkpath(buf);
+   if (!ok)
+     {
+        ERR("Problem acessing Elementary's user configuration directory: %s",
+            buf);
+        return EINA_FALSE;
+     }
+
+   if (!_elm_config_profile_save())
+     return EINA_FALSE;
+
+   buf[len] = '/';
+   len++;
+
+   if (len + sizeof("base.cfg") >= sizeof(buf) - len)
+     return EINA_FALSE;
+
+   memcpy(buf + len, "base.cfg", sizeof("base.cfg"));
+   len += sizeof("base.cfg") - 1;
+
+   if (len + sizeof(".tmp") >= sizeof(buf))
+     return EINA_FALSE;
+
+   memcpy(buf2, buf, len);
+   memcpy(buf2 + len, ".tmp", sizeof(".tmp"));
+
+   ef = eet_open(buf2, EET_FILE_MODE_WRITE);
+   if (!ef)
+     return EINA_FALSE;
+
+   ok = eet_data_write(ef, _config_edd, "config", _elm_config, 1);
+   if (!ok)
+     goto err;
+
+   err = _elm_config_eet_close_error_get(ef, buf2);
+   if (err)
+     {
+        ERR("%s", err);
+        free((void *)err);
+        goto err;
+     }
+
+   ret = ecore_file_mv(buf2, buf);
+   if (!ret)
+     {
+        ERR("Error saving Elementary's configuration file");
+        goto err;
+     }
+
+   ecore_file_unlink(buf2);
+   return EINA_TRUE;
+
+err:
+   ecore_file_unlink(buf2);
+   return EINA_FALSE;
+}
+
+static void
+_config_update(void)
+{
+   Elm_Config *tcfg;
+
+   tcfg = _config_system_load();
+   if (!tcfg)
+     {
+        /* weird profile or something? We should probably fill
+         * with hardcoded defaults, or get from default previx */
+          return;
+     }
+#define IFCFG(v)   if ((_elm_config->config_version & 0xffff) < (v)) {
+#define IFCFGELSE } else {
+#define IFCFGEND  }
+#define COPYVAL(x) do {_elm_config->x = tcfg->x; } while(0)
+#define COPYPTR(x) do {_elm_config->x = tcfg->x; tcfg->x = NULL; } while(0)
+#define COPYSTR(x) COPYPTR(x)
+
+     /* we also need to update for property changes in the root window
+      * if needed, but that will be dependent on new properties added
+      * with each version */
+
+     IFCFG(0x0003);
+     COPYVAL(longpress_timeout);
+     IFCFGEND;
+
+#undef COPYSTR
+#undef COPYPTR
+#undef COPYVAL
+#undef IFCFGEND
+#undef IFCFGELSE
+#undef IFCFG
+
+     /* after updating user config, we must save */
+}
+
+static void
+_env_get(void)
+{
+   char *s;
+   double friction;
+
+   s = getenv("ELM_ENGINE");
+   if (s)
+     {
+        if ((!strcasecmp(s, "x11")) ||
+            (!strcasecmp(s, "x")) ||
+            (!strcasecmp(s, "software-x11")) ||
+            (!strcasecmp(s, "software_x11")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_X11);
+        else if ((!strcasecmp(s, "opengl")) ||
+                 (!strcasecmp(s, "gl")) ||
+                 (!strcasecmp(s, "opengl-x11")) ||
+                 (!strcasecmp(s, "opengl_x11")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_X11);
+        else if ((!strcasecmp(s, "x11-8")) ||
+                 (!strcasecmp(s, "x18")) ||
+                 (!strcasecmp(s, "software-8-x11")) ||
+                 (!strcasecmp(s, "software_8_x11")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_8_X11);
+        else if ((!strcasecmp(s, "x11-16")) ||
+                 (!strcasecmp(s, "x16")) ||
+                 (!strcasecmp(s, "software-16-x11")) ||
+                 (!strcasecmp(s, "software_16_x11")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_X11);
+        else if ((!strcasecmp(s, "xrender")) ||
+                 (!strcasecmp(s, "xr")) ||
+                 (!strcasecmp(s, "xrender-x11")) ||
+                 (!strcasecmp(s, "xrender_x11")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_XRENDER_X11);
+        else if ((!strcasecmp(s, "fb")) ||
+                 (!strcasecmp(s, "software-fb")) ||
+                 (!strcasecmp(s, "software_fb")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_FB);
+        else if ((!strcasecmp(s, "directfb")) ||
+                 (!strcasecmp(s, "dfb")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_DIRECTFB);
+        else if ((!strcasecmp(s, "sdl")) ||
+                 (!strcasecmp(s, "software-sdl")) ||
+                 (!strcasecmp(s, "software_sdl")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_SDL);
+        else if ((!strcasecmp(s, "sdl-16")) ||
+                 (!strcasecmp(s, "software-16-sdl")) ||
+                 (!strcasecmp(s, "software_16_sdl")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_SDL);
+        else if ((!strcasecmp(s, "opengl-sdl")) ||
+                 (!strcasecmp(s, "opengl_sdl")) ||
+                 (!strcasecmp(s, "gl-sdl")) ||
+                 (!strcasecmp(s, "gl_sdl")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_SDL);
+        else if ((!strcasecmp(s, "gdi")) ||
+                 (!strcasecmp(s, "software-gdi")) ||
+                 (!strcasecmp(s, "software_gdi")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_WIN32);
+        else if ((!strcasecmp(s, "wince-gdi")) ||
+                 (!strcasecmp(s, "software-16-wince-gdi")) ||
+                 (!strcasecmp(s, "software_16_wince_gdi")))
+          eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_WINCE);
+     }
+
+   s = getenv("ELM_THUMBSCROLL_ENABLE");
+   if (s) _elm_config->thumbscroll_enable = !!atoi(s);
+   s = getenv("ELM_THUMBSCROLL_THRESHOLD");
+   if (s) _elm_config->thumbscroll_threshold = atoi(s);
+   // FIXME: floatformat locale issues here 1.0 vs 1,0 - should just be 1.0
+   s = getenv("ELM_THUMBSCROLL_MOMENTUM_THRESHOLD");
+   if (s) _elm_config->thumbscroll_momentum_threshold = atof(s);
+   s = getenv("ELM_THUMBSCROLL_FRICTION");
+   if (s) _elm_config->thumbscroll_friction = atof(s);
+   s = getenv("ELM_THUMBSCROLL_BOUNCE_ENABLE");
+   if (s) _elm_config->thumbscroll_bounce_enable = !!atoi(s);
+   s = getenv("ELM_THUMBSCROLL_BOUNCE_FRICTION");
+   if (s) _elm_config->thumbscroll_bounce_friction = atof(s);
+   s = getenv("ELM_PAGE_SCROLL_FRICTION");
+   if (s) _elm_config->page_scroll_friction = atof(s);
+   s = getenv("ELM_BRING_IN_SCROLL_FRICTION");
+   if (s) _elm_config->bring_in_scroll_friction = atof(s);
+   s = getenv("ELM_ZOOM_FRICTION");
+   if (s) _elm_config->zoom_friction = atof(s);
+   s = getenv("ELM_THUMBSCROLL_BORDER_FRICTION");
+   if (s)
+     {
+        friction = atof(s);
+        if (friction < 0.0)
+          friction = 0.0;
+
+        if (friction > 1.0)
+          friction = 1.0;
+
+        _elm_config->thumbscroll_border_friction = friction;
+     }
+   s = getenv("ELM_THEME");
+   if (s) eina_stringshare_replace(&_elm_config->theme, s);
+
+   s = getenv("ELM_FONT_HINTING");
+   if (s)
+     {
+        if      (!strcasecmp(s, "none")) _elm_config->font_hinting = 0;
+        else if (!strcasecmp(s, "auto"))
+          _elm_config->font_hinting = 1;
+        else if (!strcasecmp(s, "bytecode"))
+          _elm_config->font_hinting = 2;
+     }
+
+   s = getenv("ELM_FONT_PATH");
+   if (s)
+     {
+        const char *p, *pp;
+        char *buf2;
+
+        EINA_LIST_FREE(_elm_config->font_dirs, p)
+          {
+             eina_stringshare_del(p);
+          }
+
+        buf2 = alloca(strlen(s) + 1);
+        p = s;
+        pp = p;
+        for (;; )
+          {
+             if ((*p == ':') || (*p == 0))
+               {
+                  int len;
+
+                  len = p - pp;
+                  strncpy(buf2, pp, len);
+                  buf2[len] = 0;
+                  _elm_config->font_dirs =
+                    eina_list_append(_elm_config->font_dirs,
+                                     eina_stringshare_add(buf2));
+                  if (*p == 0) break;
+                  p++;
+                  pp = p;
+               }
+             else
+               {
+                  if (*p == 0) break;
+                  p++;
+               }
+          }
+     }
+
+   s = getenv("ELM_IMAGE_CACHE");
+   if (s) _elm_config->image_cache = atoi(s);
+
+   s = getenv("ELM_FONT_CACHE");
+   if (s) _elm_config->font_cache = atoi(s);
+
+   s = getenv("ELM_SCALE");
+   if (s) _elm_config->scale = atof(s);
+
+   _elm_config->finger_size =
+     (double)_elm_config->finger_size * _elm_config->scale;
+   s = getenv("ELM_FINGER_SIZE");
+   if (s) _elm_config->finger_size = atoi(s);
+
+   s = getenv("ELM_FPS");
+   if (s) _elm_config->fps = atof(s);
+   if (_elm_config->fps < 1.0) _elm_config->fps = 1.0;
+
+   s = getenv("ELM_MODULES");
+   if (s) eina_stringshare_replace(&_elm_config->modules, s);
+
+   s = getenv("ELM_TOOLTIP_DELAY");
+   if (s)
+     {
+        double delay = atof(s);
+        if (delay >= 0.0)
+          _elm_config->tooltip_delay = delay;
+     }
+
+   s = getenv("ELM_CURSOR_ENGINE_ONLY");
+   if (s) _elm_config->cursor_engine_only = !!atoi(s);
+
+   s = getenv("ELM_FOCUS_HIGHLIGHT_ENABLE");
+   if (s) _elm_config->focus_highlight_enable = !!atoi(s);
+
+   s = getenv("ELM_FOCUS_HIGHLIGHT_ANIMATE");
+   if (s) _elm_config->focus_highlight_animate = !!atoi(s);
+
+   s = getenv("ELM_TOOLBAR_SHRINK_MODE");
+   if (s) _elm_config->toolbar_shrink_mode = atoi(s);
+
+   s = getenv("ELM_FILESELECTOR_EXPAND_ENABLE");
+   if (s) _elm_config->fileselector_expand_enable = !!atoi(s);
+
+   s = getenv("ELM_INWIN_DIALOGS_ENABLE");
+   if (s) _elm_config->inwin_dialogs_enable = !!atoi(s);
+
+   s = getenv("ELM_ICON_SIZE");
+   if (s) _elm_config->icon_size = atoi(s);
+
+   s = getenv("ELM_LONGPRESS_TIMEOUT");
+   if (s) _elm_config->longpress_timeout = atof(s);
+   if (_elm_config->longpress_timeout < 0.0)
+     _elm_config->longpress_timeout = 0.0;
+}
+
+void
+_elm_config_init(void)
+{
+   _desc_init();
+   _profile_fetch_from_conf();
+   _config_load();
+   _env_get();
+   _config_apply();
+   _elm_config_font_overlay_apply();
+   _elm_recache();
+}
+
+void
+_elm_config_sub_init(void)
+{
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+   if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+       ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
+       ENGINE_COMPARE(ELM_XRENDER_X11) ||
+       ENGINE_COMPARE(ELM_OPENGL_X11))
+#undef ENGINE_COMPARE
+     {
+#ifdef HAVE_ELEMENTARY_X
+        unsigned int val = 1000;
+
+        if (!ecore_x_init(NULL))
+          {
+             ERR("Cannot connect to X11 display. check $DISPLAY variable");
+             exit(1);
+          }
+        _root_1st = ecore_x_window_root_first_get();
+
+        if (!ecore_x_screen_is_composited(0))
+          _elm_config->compositing = 0;
+
+        ecore_x_atoms_get(_atom_names, ATOM_COUNT, _atom);
+        ecore_x_event_mask_set(_root_1st,
+                               ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
+        _prop_change_handler = ecore_event_handler_add
+            (ECORE_X_EVENT_WINDOW_PROPERTY, _prop_change, NULL);
+        if (!getenv("ELM_SCALE"))
+          {
+             if (ecore_x_window_prop_card32_get(_root_1st,
+                                                _atom[ATOM_E_SCALE],
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    {
+                       _elm_config->scale = (double)val / 1000.0;
+     // FIXME: hack until e export finger size too
+                       if (!getenv("ELM_FINGER_SIZE"))
+                         {
+                            _elm_config->finger_size = 40.0 * _elm_config->scale;
+                         }
+                       edje_scale_set(_elm_config->scale);
+                    }
+               }
+          }
+        if (!getenv("ELM_FINGER_SIZE"))
+          {
+             if (ecore_x_window_prop_card32_get(_root_1st,
+                                                _atom[ATOM_E_FINGER_SIZE],
+                                                &val, 1) > 0)
+               {
+                  if (val > 0)
+                    {
+                       _elm_config->finger_size = val;
+                    }
+               }
+          }
+        if (!getenv("ELM_THEME"))
+          {
+             char *s;
+
+             s = ecore_x_window_prop_string_get(_root_1st,
+                                                _atom[ATOM_E_THEME]);
+             if (s)
+               {
+                  eina_stringshare_replace(&_elm_config->theme, s);
+                  _elm_theme_parse(NULL, s);
+                  free(s);
+               }
+          }
+        if (!getenv("ELM_PROFILE"))
+          {
+             char *s;
+
+             s = ecore_x_window_prop_string_get(_root_1st,
+                                                _atom[ATOM_E_PROFILE]);
+             if (s)
+               {
+                  int changed = 0;
+
+                  if (_elm_profile)
+                    {
+                       if (strcmp(_elm_profile, s)) changed = 1;
+                       free(_elm_profile);
+                    }
+                  _elm_profile = s;
+                  if (changed) _prop_config_get();
+               }
+          }
+#endif
+     }
+   _config_sub_apply();
+}
+
+void
+_elm_config_reload(void)
+{
+   _config_free();
+   _config_load();
+   _config_apply();
+   _elm_config_font_overlay_apply();
+   _elm_rescale();
+   _elm_recache();
+}
+
+void
+_elm_config_engine_set(const char *engine)
+{
+   if (_elm_config->engine && strcmp(_elm_config->engine, engine))
+     eina_stringshare_del(_elm_config->engine);
+
+   _elm_config->engine = eina_stringshare_add(engine);
+}
+
+void
+_elm_config_profile_set(const char *profile)
+{
+   Eina_Bool changed = EINA_FALSE;
+
+   if (_elm_profile)
+     {
+        if (strcmp(_elm_profile, profile))
+          changed = 1;
+        free(_elm_profile);
+     }
+
+   _elm_profile = strdup(profile);
+
+   if (changed)
+     {
+        _config_free();
+        _config_load();
+        _config_apply();
+        _elm_config_font_overlay_apply();
+        _elm_rescale();
+        _elm_recache();
+     }
+}
+
+void
+_elm_config_shutdown(void)
+{
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+   if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+       ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
+       ENGINE_COMPARE(ELM_XRENDER_X11) ||
+       ENGINE_COMPARE(ELM_OPENGL_X11))
+#undef ENGINE_COMPARE
+     {
+#ifdef HAVE_ELEMENTARY_X
+        ecore_event_handler_del(_prop_change_handler);
+        _prop_change_handler = NULL;
+#endif
+     }
+   _config_free();
+   if (_elm_profile)
+     {
+        free(_elm_profile);
+        _elm_profile = NULL;
+     }
+   _desc_shutdown();
+}
+
diff --git a/src/lib/elm_conform.c b/src/lib/elm_conform.c
new file mode 100644 (file)
index 0000000..34e2e39
--- /dev/null
@@ -0,0 +1,346 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Conformant Conformant
+ * 
+ * The aim is to provide a widget that can be used in elementary apps to 
+ * account for space taken up by the indicator & softkey windows when running 
+ * the illume2 module of E17.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+struct _Widget_Data 
+{
+   Evas_Object *base;
+   Evas_Object *shelf, *panel;
+   Evas_Object *content;
+   Ecore_Event_Handler *prop_hdl;
+   struct {
+      Ecore_Animator *animator; // animaton timer
+      double start; // time started
+      Evas_Coord auto_x, auto_y; // desired delta
+      Evas_Coord x, y; // current delta
+   } delta;
+};
+
+/* local function prototypes */
+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 Eina_Bool _prop_change(void *data, int type, void *event);
+
+/* local functions */
+static void 
+_del_hook(Evas_Object *obj) 
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->prop_hdl) ecore_event_handler_del(wd->prop_hdl);
+   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, "conformant", "base", elm_widget_style_get(obj));
+   if (wd->content)
+     edje_object_part_swallow(wd->base, "elm.swallow.content", wd->content);
+   edje_object_scale_set(wd->base, 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 mw = -1, mh = -1;
+   if (!wd) return;
+   edje_object_size_min_calc(wd->base, &mw, &mh);
+   evas_object_size_hint_min_set(obj, mw, mh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+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;
+   if (sub == wd->content)
+     {
+        evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+        wd->content = NULL;
+        _sizing_eval(obj);
+     }
+}
+
+/* unused now - but meant to be for making sure the focused widget is always
+ * visible when the vkbd comes and goes by moving the conformant obj (and thus
+ * its children) to  show the focused widget (and if focus changes follow)
+
+static Evas_Object *
+_focus_object_get(const Evas_Object *obj)
+{
+   Evas_Object *win, *foc;
+   
+   win = elm_widget_top_get(obj);
+   if (!win) return NULL;
+   foc = elm_widget_top_get(win);
+}
+
+static void
+_focus_object_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   evas_object_geometry_get(obj, x, y, w, h);
+}
+
+static void
+_focus_change_del(void *data, Evas_Object *obj, void *event_info)
+{
+   // called from toplevel when the focused window shanges
+}
+
+static void
+_autoscroll_move(Evas_Object *obj)
+{
+   // move conformant edje by delta to show focused widget
+}
+
+static void
+_autoscroll_mode_enable(Evas_Object *obj)
+{
+   // called when autoscroll mode should be on - content area smaller than
+   // its min size
+   // 1. get focused object
+   // 2. if not in visible conformant area calculate delta needed to
+   //    get it in
+   // 3. store delta and call _autoscroll_move() which either asanimates
+   //    or jumps right there
+}
+
+static void
+_autoscroll_mode_disable(Evas_Object *obj)
+{
+   // called when autoscroll mode should be off - set delta to 0 and
+   // call _autoscroll_move()
+}
+*/
+
+static Eina_Bool
+_prop_change(void *data, int type __UNUSED__, void *event) 
+{
+#ifdef HAVE_ELEMENTARY_X
+   Ecore_X_Event_Window_Property *ev;
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_PASS_ON;
+   ev = event;
+   if (ev->atom == ECORE_X_ATOM_E_ILLUME_ZONE) 
+     {
+        Ecore_X_Window zone;
+        int sh = -1;
+
+        zone = ecore_x_e_illume_zone_get(ev->win);
+        ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
+        if (sh < 0) sh = 0;
+        evas_object_size_hint_min_set(wd->shelf, -1, sh);
+        evas_object_size_hint_max_set(wd->shelf, -1, sh);
+        sh = -1;
+        ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
+        if (sh < 0) sh = 0;
+        evas_object_size_hint_min_set(wd->panel, -1, sh);
+        evas_object_size_hint_max_set(wd->panel, -1, sh);
+     }
+   else if (ev->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY) 
+     {
+        Ecore_X_Window zone;
+        int sh = -1;
+
+        zone = ecore_x_e_illume_zone_get(ev->win);
+        ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
+        if (sh < 0) sh = 0;
+        evas_object_size_hint_min_set(wd->shelf, -1, sh);
+        evas_object_size_hint_max_set(wd->shelf, -1, sh);
+     }
+   else if (ev->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY) 
+     {
+        Ecore_X_Window zone;
+        int sh = -1;
+
+        zone = ecore_x_e_illume_zone_get(ev->win);
+        ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
+        if (sh < 0) sh = 0;
+        evas_object_size_hint_min_set(wd->panel, -1, sh);
+        evas_object_size_hint_max_set(wd->panel, -1, sh);
+     }
+   else if (ev->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY) 
+     {
+        Ecore_X_Window zone;
+        int ky = -1;
+
+        printf("Keyboard Geometry Changed\n");
+        zone = ecore_x_e_illume_zone_get(ev->win);
+        ecore_x_e_illume_keyboard_geometry_get(zone, NULL, &ky, NULL, NULL);
+        printf("\tGeom: %d\n", ky);
+     }
+#endif
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+/**
+ * Add a new Conformant object
+ * 
+ * @param parent The parent object
+ * @return The new conformant object or NULL if it cannot be created
+ * 
+ * @ingroup Conformant
+ */
+EAPI Evas_Object *
+elm_conformant_add(Evas_Object *parent) 
+{
+   Evas_Object *obj;
+   Evas *evas;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+
+   evas = evas_object_evas_get(parent);
+   if (!evas) return NULL;
+
+   obj = elm_widget_add(evas);
+   ELM_SET_WIDTYPE(widtype, "conformant");
+   elm_widget_type_set(obj, "conformant");
+   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, EINA_FALSE);
+
+   wd->base = edje_object_add(evas);
+   _elm_theme_object_set(obj, wd->base, "conformant", "base", "default");
+   elm_widget_resize_object_set(obj, wd->base);
+
+#ifdef HAVE_ELEMENTARY_X
+   Ecore_X_Window zone, xwin;
+   int sh = -1;
+
+   xwin = elm_win_xwindow_get(parent);
+   zone = ecore_x_e_illume_zone_get(xwin);
+
+   ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
+   if (sh < 0) sh = 0;
+   wd->shelf = evas_object_rectangle_add(evas);
+   evas_object_color_set(wd->shelf, 0, 0, 0, 0);
+   evas_object_size_hint_min_set(wd->shelf, -1, sh);
+   evas_object_size_hint_max_set(wd->shelf, -1, sh);
+   edje_object_part_swallow(wd->base, "elm.swallow.shelf", wd->shelf);
+
+   sh = -1;
+   ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
+   if (sh < 0) sh = 0;
+   wd->panel = evas_object_rectangle_add(evas);
+   evas_object_color_set(wd->panel, 0, 0, 0, 0);
+   evas_object_size_hint_min_set(wd->panel, -1, sh);
+   evas_object_size_hint_max_set(wd->panel, -1, sh);
+   edje_object_part_swallow(wd->base, "elm.swallow.panel", wd->panel);
+
+   wd->prop_hdl = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, 
+                                          _prop_change, obj);
+   // FIXME: get kbd region prop
+#endif
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the content of the conformant widget
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_conformat_content_unset() function.
+ *
+ * @param obj The conformant object
+ * @return The content that was being used
+ *
+ * @ingroup Conformant
+ */
+EAPI void
+elm_conformant_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content) evas_object_del(wd->content);
+   wd->content = content;
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+       evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->base, "elm.swallow.content", content);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the content of the conformant widget
+ *
+ * Return the content object which is set for this widget;
+ *
+ * @param obj The conformant object
+ * @return The content that is being used
+ *
+ * @ingroup Conformant
+ */
+EAPI Evas_Object *
+elm_conformant_content_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->content;
+}
+
+/**
+ * Unset the content of the conformant widget
+ *
+ * Unparent and return the content object which was set for this widget;
+ *
+ * @param obj The conformant object
+ * @return The content that was being used
+ *
+ * @ingroup Conformant
+ */
+EAPI Evas_Object *
+elm_conformant_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *content;
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   content = wd->content;
+   elm_widget_sub_object_del(obj, wd->content);
+   edje_object_part_unswallow(wd->base, wd->content);
+   wd->content = NULL;
+   return content;
+}
diff --git a/src/lib/elm_diskselector.c b/src/lib/elm_diskselector.c
new file mode 100644 (file)
index 0000000..fe34ef9
--- /dev/null
@@ -0,0 +1,1543 @@
+/**
+ * @defgroup Diskselector
+ *
+ * A diskselector is a kind of list widget. It scrolls horizontally,
+ * and can contain label and icon objects. Three items are displayed
+ * with the selected on the middle.
+ *
+ * It can act like a circular list with round mode and labels can be
+ * reduced for a defined lenght for side items.
+ *
+ * Signal emitted by this widget:
+ * "selected" - when item is selected (scroller stops)
+ */
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#ifndef MAX
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *self;
+   Evas_Object *scroller;
+   Evas_Object *main_box;
+   Evas_Object *left_blank;
+   Evas_Object *right_blank;
+   Elm_Diskselector_Item *selected_item;
+   Elm_Diskselector_Item *first;
+   Elm_Diskselector_Item *second;
+   Elm_Diskselector_Item *s_last;
+   Elm_Diskselector_Item *last;
+   Eina_List *items;
+   Eina_List *r_items;
+   int item_count, len_threshold, len_side;
+   Ecore_Idler *idler;
+   Ecore_Idler *check_idler;
+   Eina_Bool init:1;
+   Eina_Bool round:1;
+};
+
+struct _Elm_Diskselector_Item
+{
+   Elm_Widget_Item base;
+   Eina_List *node;
+   Evas_Object *icon;
+   const char *label;
+   Evas_Smart_Cb func;
+};
+
+static const char *widtype = NULL;
+
+#define ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, ...)                    \
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
+   ELM_CHECK_WIDTYPE(it->base.widget, widtype) __VA_ARGS__;
+
+static Eina_Bool _move_scroller(void *data);
+static void _del_hook(Evas_Object * obj);
+static void _del_pre_hook(Evas_Object * obj);
+static void _sizing_eval(Evas_Object * obj);
+static void _theme_hook(Evas_Object * obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info);
+static void _sub_del(void *data, Evas_Object * obj, void *event_info);
+static void _round_items_del(Widget_Data *wd);
+static void _scroller_move_cb(void *data, Evas_Object *obj, void *event_info);
+
+static const char SIG_SELECTED[] = "selected";
+static const Evas_Smart_Cb_Description _signals[] = {
+       {SIG_SELECTED, ""},
+       {NULL, NULL}
+};
+
+static void
+_diskselector_object_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd;
+   Evas_Coord w, h, minw = -1, minh = -1;
+
+   wd = elm_widget_data_get(data);
+   if (!wd) return;
+
+   elm_coords_finger_size_adjust(6, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(elm_smart_scroller_edje_object_get(
+         wd->scroller), &minw, &minh, minw, minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+
+   evas_object_geometry_get(wd->scroller, NULL, NULL, &w, &h);
+   if (wd->round)
+     evas_object_resize(wd->main_box, w / 3 * (wd->item_count + 4), h);
+   else
+     evas_object_resize(wd->main_box, w / 3 * (wd->item_count + 2), h);
+
+   elm_smart_scroller_paging_set(wd->scroller, 0, 0,
+                                 (int)(w / 3), 0);
+
+   if (!wd->idler)
+     wd->idler = ecore_idler_add(_move_scroller, data);
+}
+
+static Elm_Diskselector_Item *
+_item_new(Evas_Object *obj, Evas_Object *icon, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   Elm_Diskselector_Item *it;
+   const char *style = elm_widget_style_get(obj);
+
+   it = elm_widget_item_new(obj, Elm_Diskselector_Item);
+   if (!it) return NULL;
+
+   it->label = eina_stringshare_add(label);
+   it->icon = icon;
+   it->func = func;
+   it->base.data = data;
+   it->base.view = edje_object_add(evas_object_evas_get(obj));
+   _elm_theme_object_set(obj, it->base.view, "diskselector", "item", style);
+   evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL,
+                                   EVAS_HINT_FILL);
+   evas_object_show(it->base.view);
+
+   if (it->label)
+        edje_object_part_text_set(it->base.view, "elm.text", it->label);
+   if (it->icon)
+     {
+        evas_object_size_hint_min_set(it->icon, 24, 24);
+        evas_object_size_hint_max_set(it->icon, 40, 40);
+        edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
+        evas_object_show(it->icon);
+        elm_widget_sub_object_add(obj, it->icon);
+     }
+   return it;
+}
+
+static void
+_item_del(Elm_Diskselector_Item *item)
+{
+   if (!item) return;
+   eina_stringshare_del(item->label);
+   if (item->icon)
+     evas_object_del(item->icon);
+   elm_widget_item_del(item);
+}
+
+static void
+_theme_data_get(Widget_Data *wd)
+{
+   const char* str;
+   str = edje_object_data_get(wd->right_blank, "len_threshold");
+   if (str) wd->len_threshold = atoi(str);
+   else wd->len_threshold = 0;
+}
+
+static void
+_del_hook(Evas_Object * obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   free(wd);
+}
+
+static void
+_del_pre_hook(Evas_Object * obj)
+{
+   Elm_Diskselector_Item *it;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->left_blank)
+     evas_object_del(wd->left_blank);
+   if (wd->right_blank)
+     evas_object_del(wd->right_blank);
+   if (wd->last)
+     {
+        eina_stringshare_del(wd->last->label);
+        evas_object_del(wd->last->base.view);
+        free(wd->last);
+     }
+   if (wd->s_last)
+     {
+        eina_stringshare_del(wd->s_last->label);
+        evas_object_del(wd->s_last->base.view);
+        free(wd->s_last);
+     }
+   if (wd->second)
+     {
+        eina_stringshare_del(wd->second->label);
+        evas_object_del(wd->second->base.view);
+        free(wd->second);
+     }
+   if (wd->first)
+     {
+        eina_stringshare_del(wd->first->label);
+        evas_object_del(wd->first->base.view);
+        free(wd->first);
+     }
+
+   EINA_LIST_FREE(wd->items, it) _item_del(it);
+   eina_list_free(wd->r_items);
+}
+
+static void
+_sizing_eval(Evas_Object * obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _diskselector_object_resize(obj, NULL, obj, NULL);
+}
+
+static void
+_theme_hook(Evas_Object * obj)
+{
+   Eina_List *l;
+   Elm_Diskselector_Item *it;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->scroller)
+     elm_smart_scroller_object_theme_set(obj, wd->scroller, "diskselector",
+                                         "base", elm_widget_style_get(obj));
+   if (wd->round)
+     {
+        EINA_LIST_FOREACH(wd->r_items, l, it)
+          {
+             _elm_theme_object_set(obj, it->base.view, "diskselector", "item",
+                                   elm_widget_style_get(obj));
+          }
+     }
+   else
+     {
+        EINA_LIST_FOREACH(wd->items, l, it)
+          {
+             _elm_theme_object_set(obj, it->base.view, "diskselector", "item",
+                                   elm_widget_style_get(obj));
+          }
+     }
+   _theme_data_get(wd);
+   _sizing_eval(obj);
+}
+
+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;
+   Elm_Diskselector_Item *it;
+   const Eina_List *l;
+
+   if (!wd) return;
+   if (!sub) abort();
+   if (sub == wd->scroller)
+     wd->scroller = NULL;
+   else
+     {
+        EINA_LIST_FOREACH(wd->items, l, it)
+          {
+             if (sub == it->icon)
+               {
+                  it->icon = NULL;
+                  _sizing_eval(obj);
+                  break;
+               }
+          }
+     }
+}
+
+static void
+_select_item(Elm_Diskselector_Item *it)
+{
+   if (!it) return;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   wd->selected_item = it;
+   if (it->func) it->func((void *)it->base.data, it->base.widget, it);
+   evas_object_smart_callback_call(it->base.widget, SIG_SELECTED, it);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->self, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->self, EINA_FALSE);
+     }
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   Elm_Diskselector_Item *it = NULL;
+   Eina_List *l;
+
+   if (!wd->selected_item) {
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+   }
+
+   if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")) ||
+       (!strcmp(ev->keyname, "Up"))  || (!strcmp(ev->keyname, "KP_Up")))
+     {
+        l = wd->selected_item->node->prev;
+        if ((!l) && (wd->round))
+          l = eina_list_last(wd->items);
+     }
+   else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")) ||
+            (!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
+     {
+        l = wd->selected_item->node->next;
+        if ((!l) && (wd->round))
+          l = wd->items;
+     }
+   else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
+     l = wd->items;
+   else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
+     l = eina_list_last(wd->items);
+   else return EINA_FALSE;
+
+   if (l)
+     it = eina_list_data_get(l);
+
+   if (it)
+     {
+        wd->selected_item = it;
+        if (!wd->idler)
+          wd->idler = ecore_idler_add(_move_scroller, obj);
+     }
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+}
+
+static int
+_check_letter(const char *str, int length)
+{
+   int code = str[length];
+
+   if (code == '\0')
+     return length;            // null string
+   else if (((code >= 65) && (code <= 90)) || ((code >= 97) && (code <= 122)))
+     return length;            // alphabet
+   else if ((48 <= code) && (code < 58))
+     return length;            // number
+   else if (((33 <= code) && (code < 47)) || ((58 <= code) && (code < 64))
+            || ((91 <= code) && (code < 96)) || ((123 <= code) && (code < 126)))
+     return length;            // special letter
+   return length - 1;
+}
+
+static Eina_Bool
+_check_string(void *data)
+{
+   int mid, steps, length, diff;
+   Elm_Diskselector_Item *it;
+   Eina_List *list, *l;
+   Evas_Coord ox, ow;
+   char buf[1024];
+   Widget_Data *wd = data;
+
+   evas_object_geometry_get(wd->scroller, &ox, NULL, &ow, NULL);
+   if (ow <= 0)
+     return EINA_FALSE;
+   if (!wd->init)
+     return EINA_FALSE;
+   if (!wd->round)
+     list = wd->items;
+   else
+     list = wd->r_items;
+
+   EINA_LIST_FOREACH(list, l, it)
+     {
+        Evas_Coord x, w;
+        int len;
+        evas_object_geometry_get(it->base.view, &x, NULL, &w, NULL);
+        /* item not visible */
+        if ((x + w <= ox) || (x >= ox + ow))
+          continue;
+
+        len = eina_stringshare_strlen(it->label);
+
+        if (x <= ox + 5)
+             edje_object_signal_emit(it->base.view, "elm,state,left_side",
+                                     "elm");
+        else if (x + w >= ox + ow - 5)
+             edje_object_signal_emit(it->base.view, "elm,state,right_side",
+                                     "elm");
+        else
+          {
+             if ((wd->len_threshold) && (len > wd->len_threshold))
+               edje_object_signal_emit(it->base.view, "elm,state,center_small",
+                                       "elm");
+             else
+               edje_object_signal_emit(it->base.view, "elm,state,center",
+                                       "elm");
+          }
+
+        if (len <= wd->len_side)
+          continue;
+
+        steps = len - wd->len_side + 1;
+        mid = x + w / 2;
+        if (mid <= ox + ow / 2)
+          diff = (ox + ow / 2) - mid;
+        else
+          diff = mid - (ox + ow / 2);
+
+        length = len - (int)(diff * steps / (ow / 3));
+        length = MAX(length, wd->len_side);
+        length = _check_letter(it->label, length);
+        strncpy(buf, it->label, length);
+        buf[length] = '\0';
+        edje_object_part_text_set(it->base.view, "elm.text", buf);
+     }
+
+   if (wd->check_idler)
+     ecore_idler_del(wd->check_idler);
+   wd->check_idler = NULL;
+   return EINA_FALSE;
+}
+
+static void
+_scroller_move_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Coord x, y, w, h, bw;
+   Widget_Data *wd = data;
+
+   _check_string(wd);
+   elm_smart_scroller_child_pos_get(obj, &x, &y);
+   elm_smart_scroller_child_viewport_size_get(obj, &w, &h);
+   if (wd->round)
+     {
+        evas_object_geometry_get(wd->main_box, NULL, NULL, &bw, NULL);
+        if (x > w / 3 * (wd->item_count + 1))
+          elm_smart_scroller_child_region_show(wd->scroller,
+                                               x - w / 3 * wd->item_count,
+                                               y, w, h);
+        else if (x < 0)
+          elm_smart_scroller_child_region_show(wd->scroller,
+                                               x + w / 3 * wd->item_count,
+                                               y, w, h);
+     }
+}
+
+static void
+_scroller_stop_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Diskselector_Item *it;
+   Widget_Data *wd = data;
+   Evas_Coord x, w, ow;
+   Eina_List *l, *list;
+
+   if (wd->idler)
+     return;
+
+   if (!wd->round)
+     list = wd->items;
+   else
+     list = wd->r_items;
+
+   evas_object_geometry_get(wd->scroller, NULL, NULL, &ow, NULL);
+   EINA_LIST_FOREACH(list, l, it)
+     {
+        evas_object_geometry_get(it->base.view, &x, NULL, &w, NULL);
+        if (abs((int)(ow / 2 - (int)(x + w / 2))) < 10)
+          break;
+     }
+
+   if (!it)
+     return;
+
+   _select_item(it);
+}
+
+static Eina_Bool
+_move_scroller(void *data)
+{
+   Evas_Object *obj = data;
+   Widget_Data *wd;
+   Eina_List *l;
+   Elm_Diskselector_Item *dit;
+   Evas_Coord y, w, h;
+   int i;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+
+   if (wd->round)
+     i = 1;
+   else
+     i = 0;
+
+   EINA_LIST_FOREACH(wd->items, l, dit)
+     {
+        if (wd->selected_item == dit)
+          break;
+        i++;
+     }
+   if (!dit)
+     {
+        wd->selected_item =
+           (Elm_Diskselector_Item *) eina_list_nth(wd->items, 0);
+        return EINA_FALSE;
+     }
+
+   evas_object_geometry_get(wd->scroller, NULL, &y, &w, &h);
+   elm_smart_scroller_child_region_show(wd->scroller, w / 3 * i, y, w, h);
+   _select_item(dit);
+   if (wd->idler)
+     {
+        ecore_idler_del(wd->idler);
+        wd->idler = NULL;
+     }
+   wd->init = EINA_TRUE;
+   _check_string(wd);
+
+   return EINA_TRUE;
+}
+
+static void
+_round_item_del(Widget_Data *wd, Elm_Diskselector_Item *it)
+{
+   if (!it) return;
+   elm_box_unpack(wd->main_box, it->base.view);
+   wd->r_items = eina_list_remove(wd->r_items, it);
+   eina_stringshare_del(it->label);
+   evas_object_del(it->base.view);
+   free(it);
+}
+
+static void
+_round_items_del(Widget_Data *wd)
+{
+   _round_item_del(wd, wd->last);
+   wd->last = NULL;
+   _round_item_del(wd, wd->s_last);
+   wd->s_last = NULL;
+   _round_item_del(wd, wd->second);
+   wd->second = NULL;
+   _round_item_del(wd, wd->first);
+   wd->first = NULL;
+}
+
+static void
+_round_items_add(Widget_Data *wd)
+{
+   Elm_Diskselector_Item *dit;
+   Elm_Diskselector_Item *it;
+
+   dit = it = eina_list_nth(wd->items, 0);
+   if (!dit) return;
+
+   if (!wd->first)
+     {
+        wd->first = _item_new(it->base.widget, it->icon, it->label, it->func,
+                              it->base.data);
+        wd->first->node = it->node;
+        wd->r_items = eina_list_append(wd->r_items, wd->first);
+     }
+
+   it = eina_list_nth(wd->items, 1);
+   if (!it)
+     it = dit;
+   if (!wd->second)
+     {
+        wd->second = _item_new(it->base.widget, it->icon, it->label, it->func,
+                               it->base.data);
+        wd->second->node = it->node;
+        wd->r_items = eina_list_append(wd->r_items, wd->second);
+     }
+
+   it = eina_list_nth(wd->items, wd->item_count - 1);
+   if (!it)
+     it = dit;
+   if (!wd->last)
+     {
+        wd->last = _item_new(it->base.widget, it->icon, it->label, it->func,
+                             it->base.data);
+        wd->last->node = it->node;
+        wd->r_items = eina_list_prepend(wd->r_items, wd->last);
+     }
+
+   it = eina_list_nth(wd->items, wd->item_count - 2);
+   if (!it)
+     it = dit;
+   if (!wd->s_last)
+     {
+        wd->s_last = _item_new(it->base.widget, it->icon, it->label, it->func,
+                               it->base.data);
+        wd->s_last->node = it->node;
+        wd->r_items = eina_list_prepend(wd->r_items, wd->s_last);
+     }
+}
+
+/**
+ * Add a new diskselector object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Diskselector
+ */
+EAPI Evas_Object *
+elm_diskselector_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   wd->self = obj = elm_widget_add(evas_object_evas_get(parent));
+   ELM_SET_WIDTYPE(widtype, "diskselector");
+   elm_widget_type_set(obj, "diskselector");
+   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);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->item_count = 0;
+   wd->round = EINA_FALSE;
+   wd->init = EINA_FALSE;
+   wd->len_side = 3;
+
+   wd->scroller = elm_smart_scroller_add(evas_object_evas_get(parent));
+   elm_smart_scroller_widget_set(wd->scroller, obj);
+   _theme_hook(obj);
+   elm_widget_resize_object_set(obj, wd->scroller);
+   elm_smart_scroller_policy_set(wd->scroller, ELM_SMART_SCROLLER_POLICY_OFF,
+                           ELM_SMART_SCROLLER_POLICY_OFF);
+   elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_TRUE, EINA_FALSE);
+   evas_object_smart_callback_add(wd->scroller, "scroll", _scroller_move_cb,
+                                  wd);
+   evas_object_smart_callback_add(wd->scroller, "animate,stop",
+                                  _scroller_stop_cb, wd);
+   _elm_theme_object_set(obj, wd->scroller, "diskselector", "base",
+                         "default");
+   evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE,
+                                  _diskselector_object_resize, obj);
+
+   wd->main_box = elm_box_add(parent);
+   elm_box_horizontal_set(wd->main_box, EINA_TRUE);
+   elm_box_homogenous_set(wd->main_box, EINA_TRUE);
+   evas_object_size_hint_weight_set(wd->main_box, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(wd->main_box, EVAS_HINT_FILL,
+                                   EVAS_HINT_FILL);
+   _elm_theme_object_set(obj, wd->main_box, "diskselector", "base",
+                         "default");
+   elm_widget_sub_object_add(obj, wd->main_box);
+
+   elm_smart_scroller_child_set(wd->scroller, wd->main_box);
+
+   wd->left_blank = edje_object_add(evas_object_evas_get(obj));
+   _elm_theme_object_set(obj, wd->left_blank, "diskselector", "item",
+                         "default");
+   evas_object_size_hint_weight_set(wd->left_blank, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(wd->left_blank, EVAS_HINT_FILL,
+                                   EVAS_HINT_FILL);
+   elm_box_pack_end(wd->main_box, wd->left_blank);
+   evas_object_show(wd->left_blank);
+
+   wd->right_blank = edje_object_add(evas_object_evas_get(obj));
+   _elm_theme_object_set(obj, wd->right_blank, "diskselector", "item",
+                         "default");
+   evas_object_size_hint_weight_set(wd->right_blank, EVAS_HINT_EXPAND,
+                                    EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(wd->right_blank, EVAS_HINT_FILL,
+                                   EVAS_HINT_FILL);
+   elm_box_pack_end(wd->main_box, wd->right_blank);
+   evas_object_show(wd->right_blank);
+
+   _theme_data_get(wd);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Get round mode
+ *
+ * If round mode is activated the items list will work like a circle list,
+ * so when the user reaches the last item, the first one will popup.
+ *
+ * @param obj The diskselector object
+ * @return if or not set round mode or false if not a valid diskselector
+ *
+ * @ingroup Diskselector
+ */
+EAPI Eina_Bool
+elm_diskselector_round_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->round;
+}
+
+/**
+ * Set round mode
+ *
+ * If round mode is activated the items list will work like a circle list,
+ * so when the user reaches the last item, the first one will popup.
+ *
+ * @param it The item of diskselector
+ * @param if or not set round mode
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_round_set(Evas_Object * obj, Eina_Bool round)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->round == round)
+     return;
+
+   wd->round = round;
+   if (round)
+     {
+        wd->r_items = eina_list_clone(wd->items);
+        elm_box_unpack(wd->main_box, wd->left_blank);
+        evas_object_hide(wd->left_blank);
+        elm_box_unpack(wd->main_box, wd->right_blank);
+        evas_object_hide(wd->right_blank);
+        if (!wd->items)
+          return;
+
+        _round_items_add(wd);
+
+        if (wd->last)
+          elm_box_pack_start(wd->main_box, wd->last->base.view);
+        if (wd->s_last)
+          elm_box_pack_start(wd->main_box, wd->s_last->base.view);
+        if (wd->first)
+          elm_box_pack_end(wd->main_box, wd->first->base.view);
+        if (wd->second)
+          elm_box_pack_end(wd->main_box, wd->second->base.view);
+     }
+   else
+     {
+        _round_items_del(wd);
+        elm_box_pack_start(wd->main_box, wd->left_blank);
+        elm_box_pack_end(wd->main_box, wd->right_blank);
+        eina_list_free(wd->r_items);
+        wd->r_items = NULL;
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the side labels max lenght
+ *
+ * @param obj The diskselector object
+ * @return The max lenght defined for side labels, or 0 if not a valid
+ * diskselector
+ *
+ * @ingroup Diskselector
+ */
+EAPI int
+elm_diskselector_side_label_lenght_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->len_side;
+}
+
+/**
+ * Set the side labels max lenght
+ *
+ * @param obj The diskselector object
+ * @param len The max lenght defined for side labels
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_side_label_lenght_set(Evas_Object *obj, int len)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->len_side = len;
+}
+
+/**
+ * Set bounce mode
+ *
+ * This will enable or disable the scroller bounce mode for the diskselector.
+ * See elm_scroller_bounce_set() for details. Horizontal bounce is enabled by
+ * default.
+ *
+ * @param obj The diskselector object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_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;
+   if (wd->scroller)
+     elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce);
+}
+
+/**
+ * Get the bounce mode
+ *
+ * @param obj The Diskselector object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_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->scroller, h_bounce, v_bounce);
+}
+
+/**
+ * Get the 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.
+ * The both are disabled by default.
+ *
+ * @param obj The diskselector object
+ * @param policy_h Horizontal scrollbar policy
+ * @param policy_v Vertical scrollbar policy
+ *
+ * @ingroup Diskselector
+ */
+
+EAPI void
+elm_diskselector_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->scroller)) return;
+   elm_smart_scroller_policy_get(wd->scroller, &s_policy_h, &s_policy_v);
+   *policy_h = (Elm_Scroller_Policy) s_policy_h;
+   *policy_v = (Elm_Scroller_Policy) s_policy_v;
+}
+
+
+/**
+ * Set the 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.
+ * The both are disabled by default.
+ *
+ * @param obj The diskselector object
+ * @param policy_h Horizontal scrollbar policy
+ * @param policy_v Vertical scrollbar policy
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((policy_h >= 3) || (policy_v >= 3)) return;
+   if (wd->scroller)
+     elm_smart_scroller_policy_set(wd->scroller, policy_h, policy_v);
+}
+
+/**
+ * Clears a diskselector of all items.
+ *
+ * @param obj The diskselector object
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Diskselector_Item *it;
+
+   if (!wd) return;
+   if (!wd->items) return;
+
+   wd->selected_item = NULL;
+   EINA_LIST_FREE(wd->items, it) _item_del(it);
+   _round_items_del(wd);
+   _sizing_eval(obj);
+}
+
+/**
+ * Returns a list of all the diskselector items.
+ *
+ * @param obj The diskselector object
+ * @return An Eina_List* of the diskselector items, or NULL on failure
+ *
+ * @ingroup Diskselector
+ */
+EAPI const Eina_List *
+elm_diskselector_items_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->items;
+}
+
+/**
+ * Appends an item to the diskselector object.
+ *
+ * @param obj The diskselector object
+ * @param label The label of the diskselector item
+ * @param icon The icon object to use for the left side of the item
+ * @param func The function to call when the item is selected
+ * @param data The data to associate with the item for related callbacks
+ *
+ * @return The created item or NULL upon failure
+ *
+ * @ingroup Diskselector
+ */
+EAPI Elm_Diskselector_Item *
+elm_diskselector_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
+{
+   Elm_Diskselector_Item *it;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   it = _item_new(obj, icon, label, func, data);
+   wd->items = eina_list_append(wd->items, it);
+   it->node = eina_list_last(wd->items);
+   wd->item_count++;
+   if (wd->round)
+     {
+        _round_items_del(wd);
+        wd->r_items = eina_list_append(wd->r_items, it);
+        _round_items_add(wd);
+        if (wd->last)
+          elm_box_pack_start(wd->main_box, wd->last->base.view);
+        if (wd->s_last)
+          elm_box_pack_start(wd->main_box, wd->s_last->base.view);
+        elm_box_pack_end(wd->main_box, it->base.view);
+        if (wd->first)
+          elm_box_pack_end(wd->main_box, wd->first->base.view);
+        if (wd->second)
+          elm_box_pack_end(wd->main_box, wd->second->base.view);
+     }
+   else
+     {
+        elm_box_unpack(wd->main_box, wd->right_blank);
+        elm_box_pack_end(wd->main_box, it->base.view);
+        elm_box_pack_end(wd->main_box, wd->right_blank);
+     }
+   if (!wd->selected_item)
+     wd->selected_item = it;
+   if (!wd->idler)
+     wd->idler = ecore_idler_add(_move_scroller, obj);
+   _sizing_eval(obj);
+   return it;
+}
+
+/**
+ * Delete the item
+ *
+ * @param it The item of diskselector
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_del(Elm_Diskselector_Item * it)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it);
+   Elm_Diskselector_Item *dit;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   if (!wd) return;
+
+   elm_box_unpack(wd->main_box, it->base.view);
+
+   if (wd->round)
+     wd->r_items = eina_list_remove(wd->r_items, it);
+
+   wd->items = eina_list_remove(wd->items, it);
+
+   if (wd->selected_item == it)
+     {
+        dit = (Elm_Diskselector_Item *) eina_list_nth(wd->items, 0);
+        if (dit != it)
+          wd->selected_item = dit;
+        else
+          wd->selected_item = eina_list_nth(wd->items, 1);
+     }
+
+   _item_del(it);
+   wd->item_count -= 1;
+
+   if (wd->round)
+     {
+        if (!wd->item_count)
+          {
+             evas_object_hide(wd->first->base.view);
+             evas_object_hide(wd->second->base.view);
+             evas_object_hide(wd->last->base.view);
+             evas_object_hide(wd->s_last->base.view);
+          }
+        else
+          {
+             dit = eina_list_nth(wd->items, 0);
+             if (dit)
+               {
+                  eina_stringshare_replace(&wd->first->label, dit->label);
+                  edje_object_part_text_set(wd->first->base.view, "elm.text",
+                                            wd->first->label);
+               }
+             dit = eina_list_nth(wd->items, 1);
+             if (dit)
+               {
+                  eina_stringshare_replace(&wd->second->label, dit->label);
+                  edje_object_part_text_set(wd->second->base.view, "elm.text",
+                                            wd->second->label);
+               }
+             dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 1);
+             if (dit)
+               {
+                  eina_stringshare_replace(&wd->last->label, dit->label);
+                  edje_object_part_text_set(wd->last->base.view, "elm.text",
+                                            wd->last->label);
+               }
+             dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 2);
+             if (dit)
+               {
+                  eina_stringshare_replace(&wd->s_last->label, dit->label);
+                  edje_object_part_text_set(wd->s_last->base.view, "elm.text",
+                                            wd->s_last->label);
+               }
+          }
+     }
+   wd->check_idler = ecore_idler_add(_check_string, wd);
+   _sizing_eval(it->base.widget);
+}
+
+/**
+ * Get the label of item
+ *
+ * @param it The item of diskselector
+ * @return The label of item
+ *
+ * @ingroup Diskselector
+ */
+EAPI const char *
+elm_diskselector_item_label_get(const Elm_Diskselector_Item * it)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, NULL);
+   return it->label;
+}
+
+/**
+ * Set the label of item
+ *
+ * @param it The item of diskselector
+ * @param label The label of item
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_label_set(Elm_Diskselector_Item * it, const char *label)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it);
+   eina_stringshare_replace(&it->label, label);
+   edje_object_part_text_set(it->base.view, "elm.text", it->label);
+}
+
+/**
+ * Get the selected item
+ *
+ * @param obj The diskselector object
+ * @return The selected diskselector item
+ *
+ * @ingroup Diskselector
+ */
+EAPI Elm_Diskselector_Item *
+elm_diskselector_selected_item_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_item;
+}
+
+/**
+ * Set the selected state of an item
+ *
+ * This sets the selected state (EINA_TRUE selected, EINA_FALSE not selected)
+ * of the given item @p it.
+ * If a new item is selected the previosly selected will be unselected.
+ * If the item @p it is unselected, the first item will be selected.
+ *
+ * @param it The diskselector item
+ * @param selected The selected state
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_selected_set(Elm_Diskselector_Item *it, Eina_Bool selected)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it);
+   Widget_Data *wd;
+   wd = elm_widget_data_get(it->base.widget);
+   if (!wd) return;
+
+   if ((wd->selected_item == it) && (selected))
+     return;
+
+   if ((wd->selected_item == it) && (!selected))
+     wd->selected_item = eina_list_data_get(wd->items);
+   else
+     wd->selected_item = it;
+
+   if (!wd->idler)
+     ecore_idler_add(_move_scroller, it->base.widget);
+}
+
+/*
+ * Get the selected state of @p item.
+ *
+ * @param it The diskselector item
+ * @return If true, the item is selected
+ *
+ * @ingroup Diskselector
+ */
+EAPI Eina_Bool
+elm_diskselector_item_selected_get(const Elm_Diskselector_Item *it)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(it->base.widget);
+   if (!wd) return EINA_FALSE;
+   return (wd->selected_item == it);
+}
+
+/**
+ * Set the function called when a diskselector item is freed.
+ *
+ * @param it The item to set the callback on
+ * @param func The function called
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_del_cb_set(Elm_Diskselector_Item *it, Evas_Smart_Cb func)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it);
+   elm_widget_item_del_cb_set(it, func);
+}
+
+/**
+ * Returns the data associated with the item.
+ *
+ * @param it The diskselector item
+ * @return The data associated with @p it
+ *
+ * @ingroup Diskselector
+ */
+EAPI void *
+elm_diskselector_item_data_get(const Elm_Diskselector_Item *it)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, NULL);
+   return elm_widget_item_data_get(it);
+}
+
+/**
+ * Returns the icon associated with the item.
+ *
+ * @param it The diskselector item
+ * @return The icon associated with @p it
+ *
+ * @ingroup Diskselector
+ */
+EAPI Evas_Object *
+elm_diskselector_item_icon_get(const Elm_Diskselector_Item *it)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, NULL);
+   return it->icon;
+}
+
+/**
+ * Sets the icon associated with the item.
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * You probably don't want, then, to have the <b>same</b> icon object set
+ * for more than one item of the diskselector.
+ *
+ * @param it The diskselector item
+ * @param icon The icon object to associate with @p it
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_icon_set(Elm_Diskselector_Item *it, Evas_Object *icon)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it);
+   if (it->icon == icon) return;
+   if (it->icon)
+     evas_object_del(it->icon);
+   it->icon = icon;
+   if (it->base.view)
+     edje_object_part_swallow(it->base.view, "elm.swallow.icon", icon);
+}
+
+/**
+ * Gets the item before @p it in the list.
+ *
+ * @param it The diskselector item
+ * @return The item before @p it, or NULL on failure
+ *
+ * @ingroup Diskselector
+ */
+EAPI Elm_Diskselector_Item *
+elm_diskselector_item_prev_get(const Elm_Diskselector_Item *it)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, NULL);
+   if (it->node->prev) return it->node->prev->data;
+   else return NULL;
+}
+
+/**
+ * Gets the item after @p it in the list.
+ *
+ * @param it The diskselector item
+ * @return The item after @p it, or NULL on failure
+ *
+ * @ingroup Diskselector
+ */
+EAPI Elm_Diskselector_Item *
+elm_diskselector_item_next_get(const Elm_Diskselector_Item *it)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, NULL);
+   if (it->node->next) return it->node->next->data;
+   else return NULL;
+}
+
+/**
+ * Get the first item in the diskselector
+ *
+ * @param obj The diskselector object
+ * @return The first item, or NULL if none
+ *
+ * @ingroup Diskselector
+ */
+EAPI Elm_Diskselector_Item *
+elm_diskselector_first_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd || !wd->items)
+     return NULL;
+
+   return eina_list_data_get(wd->items);
+}
+
+/**
+ * Get the last item in the diskselector
+ *
+ * @param obj The diskselector object
+ * @return The last item, or NULL if none
+ *
+ * @ingroup Diskselector
+ */
+EAPI Elm_Diskselector_Item *
+elm_diskselector_last_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Widget_Data *wd;
+   wd = elm_widget_data_get(obj);
+   if (!wd || !wd->items)
+     return NULL;
+
+   return eina_list_data_get(eina_list_last(wd->items));
+}
+
+/**
+ * Set the text to be shown in the diskselector item.
+ *
+ * @param item Target item
+ * @param text The text to set in the content
+ *
+ * Setup the text as tooltip to object. The item can have only one tooltip,
+ * so any previous tooltip data is removed.
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_tooltip_text_set(Elm_Diskselector_Item *item, const char *text)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_text_set(item, text);
+}
+
+/**
+ * Set the content to be shown in the tooltip item
+ *
+ * Setup the tooltip to item. The item can have only one tooltip,
+ * so any previous tooltip data is removed. @p func(with @p data) will
+ * be called every time that need show the tooltip and it should
+ * return a valid Evas_Object. This object is then managed fully by
+ * tooltip system and is deleted when the tooltip is gone.
+ *
+ * @param item the diskselector item being attached a tooltip.
+ * @param func the function used to create the tooltip contents.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_diskselector_item_tooltip_unset() or the owner @a item
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is the item.
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_tooltip_content_cb_set(Elm_Diskselector_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
+}
+
+/**
+ * Unset tooltip from item
+ *
+ * @param item diskselector item to remove previously set tooltip.
+ *
+ * Remove tooltip from item. The callback provided as del_cb to
+ * elm_diskselector_item_tooltip_content_cb_set() will be called to notify
+ * it is not used anymore.
+ *
+ * @see elm_diskselector_item_tooltip_content_cb_set()
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_tooltip_unset(Elm_Diskselector_Item *item)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_unset(item);
+}
+
+/**
+ * Sets a different style for this item tooltip.
+ *
+ * @note before you set a style you should define a tooltip with
+ *       elm_diskselector_item_tooltip_content_cb_set() or
+ *       elm_diskselector_item_tooltip_text_set()
+ *
+ * @param item diskselector item with tooltip already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_tooltip_style_set(Elm_Diskselector_Item *item, const char *style)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_style_set(item, style);
+}
+
+/**
+ * Get the style for this item tooltip.
+ *
+ * @param item diskselector item with tooltip already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a tooltip set, then NULL is returned.
+ *
+ * @ingroup Diskselector
+ */
+EAPI const char *
+elm_diskselector_item_tooltip_style_get(const Elm_Diskselector_Item *item)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_tooltip_style_get(item);
+}
+
+/**
+ * Set the cursor to be shown when mouse is over the diskselector item
+ *
+ * @param item Target item
+ * @param cursor the cursor name to be used.
+ *
+ * @see elm_object_cursor_set()
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_cursor_set(Elm_Diskselector_Item *item, const char *cursor)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_set(item, cursor);
+}
+
+/**
+ * Get the cursor to be shown when mouse is over the diskselector item
+ *
+ * @param item diskselector item with cursor already set.
+ * @return the cursor name.
+ *
+ * @ingroup Diskselector
+ */
+EAPI const char *
+elm_diskselector_item_cursor_get(const Elm_Diskselector_Item *item)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_get(item);
+}
+
+/**
+ * Unset the cursor to be shown when mouse is over the diskselector item
+ *
+ * @param item Target item
+ *
+ * @see elm_object_cursor_unset()
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_cursor_unset(Elm_Diskselector_Item *item)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_unset(item);
+}
+
+/**
+ * Sets a different style for this item cursor.
+ *
+ * @note before you set a style you should define a cursor with
+ *       elm_diskselector_item_cursor_set()
+ *
+ * @param item diskselector item with cursor already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_cursor_style_set(Elm_Diskselector_Item *item, const char *style)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_style_set(item, style);
+}
+
+/**
+ * Get the style for this item cursor.
+ *
+ * @param item diskselector item with cursor already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup Diskselector
+ */
+EAPI const char *
+elm_diskselector_item_cursor_style_get(const Elm_Diskselector_Item *item)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_style_get(item);
+}
+
+/**
+ * Set if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a cursor
+ * with elm_object_cursor_set(). By default it will only look for cursors
+ * provided by the engine.
+ *
+ * @param item widget item with cursor already set.
+ * @param engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well.
+ *
+ * @ingroup Diskselector
+ */
+EAPI void
+elm_diskselector_item_cursor_engine_only_set(Elm_Diskselector_Item *item, Eina_Bool engine_only)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_engine_only_set(item, engine_only);
+}
+
+/**
+ * Get the cursor engine only usage for this item cursor.
+ *
+ * @param item widget item with cursor already set.
+ * @return engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well. If
+ *         the object does not have a cursor set, then EINA_FALSE is returned.
+ *
+ * @ingroup Diskselector
+ */
+EAPI Eina_Bool
+elm_diskselector_item_cursor_engine_only_get(const Elm_Diskselector_Item *item)
+{
+   ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
+   return elm_widget_item_cursor_engine_only_get(item);
+}
diff --git a/src/lib/elm_entry.c b/src/lib/elm_entry.c
new file mode 100644 (file)
index 0000000..9f08458
--- /dev/null
@@ -0,0 +1,2791 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Entry Entry
+ *
+ * An entry is a convenience widget which shows
+ * a box that the user can enter text into.  Unlike a
+ * @ref Scrolled_Entry widget, entries DO NOT scroll with user
+ * input.  Entry widgets are capable of expanding past the
+ * boundaries of the window, thus resizing the window to its
+ * own length.
+ *
+ * You can also insert "items" in the entry with:
+ *
+ * \<item size=16x16 vsize=full href=emoticon/haha\>\</item\>
+ *
+ * for example. sizing can be set bu size=WxH, relsize=WxH or absize=WxH with
+ * vsize=ascent or vsize=full. the href=NAME sets the item name. Entry
+ * supports a list of emoticon names by default. These are:
+ *
+ * - emoticon/angry
+ * - emoticon/angry-shout
+ * - emoticon/crazy-laugh
+ * - emoticon/evil-laugh
+ * - emoticon/evil
+ * - emoticon/goggle-smile
+ * - emoticon/grumpy
+ * - emoticon/grumpy-smile
+ * - emoticon/guilty
+ * - emoticon/guilty-smile
+ * - emoticon/haha
+ * - emoticon/half-smile
+ * - emoticon/happy-panting
+ * - emoticon/happy
+ * - emoticon/indifferent
+ * - emoticon/kiss
+ * - emoticon/knowing-grin
+ * - emoticon/laugh
+ * - emoticon/little-bit-sorry
+ * - emoticon/love-lots
+ * - emoticon/love
+ * - emoticon/minimal-smile
+ * - emoticon/not-happy
+ * - emoticon/not-impressed
+ * - emoticon/omg
+ * - emoticon/opensmile
+ * - emoticon/smile
+ * - emoticon/sorry
+ * - emoticon/squint-laugh
+ * - emoticon/surprised
+ * - emoticon/suspicious
+ * - emoticon/tongue-dangling
+ * - emoticon/tongue-poke
+ * - emoticon/uh
+ * - emoticon/unhappy
+ * - emoticon/very-sorry
+ * - emoticon/what
+ * - emoticon/wink
+ * - emoticon/worried
+ * - emoticon/wtf
+ *
+ * These are built-in currently, but you can add your own item provieer that
+ * can create inlined objects in the text and fill the space allocated to the
+ * item with a custom object of your own.
+ *
+ * See the entry test for some more examples of use of this.
+ *
+ * Entries have functions to load a text file, display it,
+ * allowing editing of it and saving of changes back to the file loaded.
+ * Changes are written back to the original file after a short delay.
+ * The file to load and save to is specified by elm_entry_file_set().
+ *
+ * Signals that you can add callbacks for are:
+ * - "changed" - The text within the entry was changed
+ * - "activated" - The entry has had editing finished and changes are to be committed (generally when enter key is pressed)
+ * - "press" - The entry has been clicked
+ * - "longpressed" - The entry has been clicked for a couple seconds
+ * - "clicked" - The entry has been clicked
+ * - "clicked,double" - The entry has been double clicked
+ * - "focused" - The entry has received focus
+ * - "unfocused" - The entry has lost focus
+ * - "selection,paste" - A paste action has occurred
+ * - "selection,copy" - A copy action has occurred
+ * - "selection,cut" - A cut action has occurred
+ * - "selection,start" - A selection has begun
+ * - "selection,changed" - The selection has changed
+ * - "selection,cleared" - The selection has been cleared
+ * - "cursor,changed" - The cursor has changed
+ * - "anchor,clicked" - The anchor has been clicked
+ */
+
+typedef struct _Mod_Api Mod_Api;
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
+typedef struct _Elm_Entry_Item_Provider Elm_Entry_Item_Provider;
+typedef struct _Elm_Entry_Text_Filter Elm_Entry_Text_Filter;
+
+struct _Widget_Data
+{
+   Evas_Object *ent;
+   Evas_Object *hoversel;
+   Ecore_Job *deferred_recalc_job;
+   Ecore_Event_Handler *sel_notify_handler;
+   Ecore_Event_Handler *sel_clear_handler;
+   Ecore_Timer *longpress_timer;
+   Ecore_Timer *delay_write;
+   /* Only for clipboard */
+   const char *cut_sel;
+   const char *text;
+   const char *file;
+   Elm_Text_Format format;
+   Evas_Coord lastw;
+   Evas_Coord downx, downy;
+   Evas_Coord cx, cy, cw, ch;
+   Eina_List *items;
+   Eina_List *item_providers;
+   Eina_List *text_filters;
+   Ecore_Job *hovdeljob;
+   Mod_Api *api; // module api if supplied
+   Eina_Bool changed : 1;
+   Eina_Bool linewrap : 1;
+   Eina_Bool char_linewrap : 1;
+   Eina_Bool single_line : 1;
+   Eina_Bool password : 1;
+   Eina_Bool editable : 1;
+   Eina_Bool selection_asked : 1;
+   Eina_Bool have_selection : 1;
+   Eina_Bool selmode : 1;
+   Eina_Bool deferred_cur : 1;
+   Eina_Bool disabled : 1;
+   Eina_Bool context_menu : 1;
+   Eina_Bool drag_selection_asked : 1;
+   Eina_Bool can_write : 1;
+   Eina_Bool autosave : 1;
+   Eina_Bool textonly : 1;
+};
+
+struct _Elm_Entry_Context_Menu_Item
+{
+   Evas_Object *obj;
+   const char *label;
+   const char *icon_file;
+   const char *icon_group;
+   Elm_Icon_Type icon_type;
+   Evas_Smart_Cb func;
+   void *data;
+};
+
+struct _Elm_Entry_Item_Provider
+{
+   Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item);
+   void *data;
+};
+
+struct _Elm_Entry_Text_Filter
+{
+   void (*func) (void *data, Evas_Object *entry, char **text);
+   void *data;
+};
+
+static const char *widtype = NULL;
+
+static Eina_Bool _drag_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data *);
+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 _on_focus_hook(void *data, Evas_Object *obj);
+static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static const char *_getbase(Evas_Object *obj);
+static void _signal_entry_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_selection_start(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_selection_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_selection_cleared(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_entry_paste_request(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_entry_copy_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_entry_cut_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_cursor_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
+
+static const char SIG_CHANGED[] = "changed";
+static const char SIG_ACTIVATED[] = "activated";
+static const char SIG_PRESS[] = "press";
+static const char SIG_LONGPRESSED[] = "longpressed";
+static const char SIG_CLICKED[] = "clicked";
+static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
+static const char SIG_FOCUSED[] = "focused";
+static const char SIG_UNFOCUSED[] = "unfocused";
+static const char SIG_SELECTION_PASTE[] = "selection,paste";
+static const char SIG_SELECTION_COPY[] = "selection,copy";
+static const char SIG_SELECTION_CUT[] = "selection,cut";
+static const char SIG_SELECTION_START[] = "selection,start";
+static const char SIG_SELECTION_CHANGED[] = "selection,changed";
+static const char SIG_SELECTION_CLEARED[] = "selection,cleared";
+static const char SIG_CURSOR_CHANGED[] = "cursor,changed";
+static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CHANGED, ""},
+  {SIG_ACTIVATED, ""},
+  {SIG_PRESS, ""},
+  {SIG_LONGPRESSED, ""},
+  {SIG_CLICKED, ""},
+  {SIG_CLICKED_DOUBLE, ""},
+  {SIG_FOCUSED, ""},
+  {SIG_UNFOCUSED, ""},
+  {SIG_SELECTION_PASTE, ""},
+  {SIG_SELECTION_COPY, ""},
+  {SIG_SELECTION_CUT, ""},
+  {SIG_SELECTION_START, ""},
+  {SIG_SELECTION_CHANGED, ""},
+  {SIG_SELECTION_CLEARED, ""},
+  {SIG_CURSOR_CHANGED, ""},
+  {SIG_ANCHOR_CLICKED, ""},
+  {NULL, NULL}
+};
+
+static Eina_List *entries = NULL;
+
+struct _Mod_Api
+{
+   void (*obj_hook) (Evas_Object *obj);
+   void (*obj_unhook) (Evas_Object *obj);
+   void (*obj_longpress) (Evas_Object *obj);
+};
+
+static Mod_Api *
+_module(Evas_Object *obj __UNUSED__)
+{
+   static Elm_Module *m = NULL;
+   if (m) goto ok; // already found - just use
+   if (!(m = _elm_module_find_as("entry/api"))) return NULL;
+   // get module api
+   m->api = malloc(sizeof(Mod_Api));
+   if (!m->api) return NULL;
+   ((Mod_Api *)(m->api)      )->obj_hook = // called on creation
+     _elm_module_symbol_get(m, "obj_hook");
+   ((Mod_Api *)(m->api)      )->obj_unhook = // called on deletion
+     _elm_module_symbol_get(m, "obj_unhook");
+   ((Mod_Api *)(m->api)      )->obj_longpress = // called on long press menu
+     _elm_module_symbol_get(m, "obj_longpress");
+   ok: // ok - return api
+   return m->api;
+}
+
+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[16384 + 1];
+
+   f = fopen(file, "rb");
+   if (!f) return NULL;
+   while ((size = fread(buf, 1, sizeof(buf) - 1, f)))
+     {
+        char *tmp_text;
+        buf[size] = 0;
+        tmp_text = _buf_append(text, buf, &len, &alloc);
+        if (!tmp_text) break;
+        text = tmp_text;
+     }
+   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(obj, "");
+        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(obj, text);
+        free(text);
+     }
+   else
+     elm_entry_entry_set(obj, "");
+}
+
+static void
+_save_markup_utf8(const char *file, const char *text)
+{
+   FILE *f;
+
+   if ((!text) || (!text[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)
+     return;
+   _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(obj));
+       break;
+      case ELM_TEXT_FORMAT_MARKUP_UTF8:
+       _save_markup_utf8(wd->file, elm_entry_entry_get(obj));
+       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
+_del_pre_hook(Evas_Object *obj)
+{
+   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);
+     }
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Entry_Context_Menu_Item *it;
+   Elm_Entry_Item_Provider *ip;
+   Elm_Entry_Text_Filter *tf;
+
+   if (wd->file) eina_stringshare_del(wd->file);
+
+   if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
+   if ((wd->api) && (wd->api->obj_unhook)) wd->api->obj_unhook(obj); // module - unhook
+
+   entries = eina_list_remove(entries, obj);
+#ifdef HAVE_ELEMENTARY_X
+   ecore_event_handler_del(wd->sel_notify_handler);
+   ecore_event_handler_del(wd->sel_clear_handler);
+#endif
+   if (wd->cut_sel) eina_stringshare_del(wd->cut_sel);
+   if (wd->text) eina_stringshare_del(wd->text);
+   if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
+   if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
+   EINA_LIST_FREE(wd->items, it)
+     {
+        eina_stringshare_del(it->label);
+        eina_stringshare_del(it->icon_file);
+        eina_stringshare_del(it->icon_group);
+        free(it);
+     }
+   EINA_LIST_FREE(wd->item_providers, ip)
+     {
+        free(ip);
+     }
+   EINA_LIST_FREE(wd->text_filters, tf)
+     {
+        free(tf);
+     }
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *t;
+
+   t = eina_stringshare_add(elm_entry_entry_get(obj));
+   _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
+   elm_entry_entry_set(obj, t);
+   eina_stringshare_del(t);
+   if (elm_widget_disabled_get(obj))
+      edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
+   edje_object_message_signal_process(wd->ent);
+   edje_object_scale_set(wd->ent, 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 (elm_widget_disabled_get(obj))
+     {
+       edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
+       wd->disabled = EINA_TRUE;
+     }
+   else
+     {
+       edje_object_signal_emit(wd->ent, "elm,state,enabled", "elm");
+       wd->disabled = EINA_FALSE;
+     }
+}
+
+static void
+_elm_win_recalc_job(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord minw = -1, minh = -1, maxh = -1;
+   Evas_Coord resw, resh, minminw;
+   if (!wd) return;
+   wd->deferred_recalc_job = NULL;
+   evas_object_geometry_get(wd->ent, NULL, NULL, &resw, &resh);
+   resh = 0;
+   edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, 0, 0);
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   minminw = minw;
+   edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, resw, 0);
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_size_hint_min_set(data, minminw, minh);
+   if (wd->single_line) maxh = minh;
+   evas_object_size_hint_max_set(data, -1, maxh);
+   if (wd->deferred_cur)
+     elm_widget_show_region_set(data, wd->cx, wd->cy, wd->cw, wd->ch);
+}
+
+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 resw, resh;
+   if (!wd) return;
+   if ((wd->linewrap) || (wd->char_linewrap))
+     {
+       evas_object_geometry_get(wd->ent, NULL, NULL, &resw, &resh);
+       if ((resw == wd->lastw) && (!wd->changed)) return;
+       wd->changed = EINA_FALSE;
+       wd->lastw = resw;
+       if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
+       wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
+     }
+   else
+     {
+       evas_object_geometry_get(wd->ent, NULL, NULL, &resw, &resh);
+       edje_object_size_min_calc(wd->ent, &minw, &minh);
+        elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       evas_object_size_hint_min_set(obj, minw, minh);
+        if (wd->single_line) maxh = minh;
+       evas_object_size_hint_max_set(obj, maxw, maxh);
+     }
+}
+
+static void
+_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *top = elm_widget_top_get(obj);
+   if (!wd) return;
+   if (!wd->editable) return;
+   if (elm_widget_focus_get(obj))
+     {
+       evas_object_focus_set(wd->ent, EINA_TRUE);
+       edje_object_signal_emit(wd->ent, "elm,action,focus", "elm");
+       if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_ON);
+       evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->ent, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->ent, EINA_FALSE);
+       if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
+       evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
+     }
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(wd->ent, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_add(wd->ent, emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(wd->ent, emission, source, func_cb,
+                                        data);
+}
+
+static void
+_on_focus_region_hook(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
+}
+
+static void
+_hoversel_position(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord cx, cy, cw, ch, x, y, mw, mh;
+   if (!wd) return;
+   evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
+   edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
+                                            &cx, &cy, &cw, &ch);
+   evas_object_size_hint_min_get(wd->hoversel, &mw, &mh);
+   if (cw < mw)
+     {
+       cx += (cw - mw) / 2;
+       cw = mw;
+     }
+   if (ch < mh)
+     {
+       cy += (ch - mh) / 2;
+       ch = mh;
+     }
+   evas_object_move(wd->hoversel, x + cx, y + cy);
+   evas_object_resize(wd->hoversel, cw, ch);
+}
+
+static void
+_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (wd->hoversel) _hoversel_position(data);
+}
+
+static void
+_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if ((wd->linewrap) || (wd->char_linewrap))
+     {
+        _sizing_eval(data);
+     }
+   if (wd->hoversel) _hoversel_position(data);
+//   Evas_Coord ww, hh;
+//   evas_object_geometry_get(wd->ent, NULL, NULL, &ww, &hh);
+}
+
+static void
+_hover_del(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   
+   if (wd->hoversel)
+     {
+        evas_object_del(wd->hoversel);
+        wd->hoversel = NULL;
+     }
+   wd->hovdeljob = NULL;
+}
+
+static void
+_dismissed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return; 
+   if (wd->hoversel) evas_object_hide(wd->hoversel);
+   if (wd->selmode)
+     {
+        if (!wd->password)
+          edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
+     }
+   elm_widget_scroll_freeze_pop(data);
+   if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
+   wd->hovdeljob = ecore_job_add(_hover_del, data);
+}
+
+static void
+_select(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->selmode = EINA_TRUE;
+   edje_object_part_text_select_none(wd->ent, "elm.text");
+   if (!wd->password)
+     edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
+   edje_object_signal_emit(wd->ent, "elm,state,select,on", "elm");
+   elm_widget_scroll_hold_push(data);
+}
+
+static void
+_paste(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
+   if (wd->sel_notify_handler)
+     {
+#ifdef HAVE_ELEMENTARY_X
+        Elm_Sel_Format formats;
+        wd->selection_asked = EINA_TRUE;
+       formats = ELM_SEL_FORMAT_MARKUP;
+       if (!wd->textonly)
+          formats |= ELM_SEL_FORMAT_IMAGE;
+       elm_selection_get(ELM_SEL_CLIPBOARD, formats, data, NULL, NULL);
+#endif
+     }
+}
+
+static void
+_store_selection(Elm_Sel_Type seltype, Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *sel;
+
+   if (!wd) return;
+   sel = edje_object_part_text_selection_get(wd->ent, "elm.text");
+   elm_selection_set(seltype, obj, ELM_SEL_FORMAT_MARKUP, sel);
+   if (seltype == ELM_SEL_CLIPBOARD)
+          eina_stringshare_replace(&wd->cut_sel, sel);
+}
+
+static void
+_cut(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   /* Store it */
+   wd->selmode = EINA_FALSE;
+   edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
+   edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
+   elm_widget_scroll_hold_pop(data);
+   _store_selection(ELM_SEL_CLIPBOARD, data);
+   edje_object_part_text_insert(wd->ent, "elm.text", "");
+   edje_object_part_text_select_none(wd->ent, "elm.text");
+}
+
+static void
+_copy(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->selmode = EINA_FALSE;
+   edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
+   edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
+   elm_widget_scroll_hold_pop(data);
+   _store_selection(ELM_SEL_CLIPBOARD, data);
+//   edje_object_part_text_select_none(wd->ent, "elm.text");
+}
+
+static void
+_cancel(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->selmode = EINA_FALSE;
+   edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
+   edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
+   elm_widget_scroll_hold_pop(data);
+   edje_object_part_text_select_none(wd->ent, "elm.text");
+}
+
+static void
+_item_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Entry_Context_Menu_Item *it = data;
+   Evas_Object *obj2 = it->obj;
+   if (it->func) it->func(it->data, obj2, NULL);
+}
+
+static Eina_Bool
+_long_press(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Object *top;
+   const Eina_List *l;
+   const Elm_Entry_Context_Menu_Item *it;
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   if ((wd->api) && (wd->api->obj_longpress))
+     {
+        wd->api->obj_longpress(data);
+     }
+   else if (wd->context_menu)
+     {
+        const char *context_menu_orientation;
+
+        if (wd->hoversel) evas_object_del(wd->hoversel);
+        else elm_widget_scroll_freeze_push(data);
+        wd->hoversel = elm_hoversel_add(data);
+        context_menu_orientation = edje_object_data_get
+          (wd->ent, "context_menu_orientation");
+        if ((context_menu_orientation) &&
+            (!strcmp(context_menu_orientation, "horizontal")))
+          elm_hoversel_horizontal_set(wd->hoversel, EINA_TRUE);
+        elm_object_style_set(wd->hoversel, "entry");
+        elm_widget_sub_object_add(data, wd->hoversel);
+        elm_hoversel_label_set(wd->hoversel, "Text");
+        top = elm_widget_top_get(data);
+        if (top) elm_hoversel_hover_parent_set(wd->hoversel, top);
+        evas_object_smart_callback_add(wd->hoversel, "dismissed", _dismissed, data);
+        if (!wd->selmode)
+          {
+             if (!wd->password)
+               elm_hoversel_item_add(wd->hoversel, "Select", NULL, ELM_ICON_NONE,
+                                     _select, data);
+             if (1) // need way to detect if someone has a selection
+               {
+                  if (wd->editable)
+                    elm_hoversel_item_add(wd->hoversel, "Paste", NULL, ELM_ICON_NONE,
+                                          _paste, data);
+               }
+          }
+        else
+          {
+             if (!wd->password)
+               {
+                  if (wd->have_selection)
+                    {
+                       elm_hoversel_item_add(wd->hoversel, "Copy", NULL, ELM_ICON_NONE,
+                                             _copy, data);
+                       if (wd->editable)
+                         elm_hoversel_item_add(wd->hoversel, "Cut", NULL, ELM_ICON_NONE,
+                                               _cut, data);
+                    }
+                  elm_hoversel_item_add(wd->hoversel, "Cancel", NULL, ELM_ICON_NONE,
+                                        _cancel, data);
+               }
+          }
+        EINA_LIST_FOREACH(wd->items, l, it)
+          {
+             elm_hoversel_item_add(wd->hoversel, it->label, it->icon_file,
+                                   it->icon_type, _item_clicked, it);
+          }
+        if (wd->hoversel)
+          {
+             _hoversel_position(data);
+             evas_object_show(wd->hoversel);
+             elm_hoversel_hover_begin(wd->hoversel);
+          }
+        edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
+        edje_object_part_text_select_abort(wd->ent, "elm.text");
+     }
+   wd->longpress_timer = NULL;
+   evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Down *ev = event_info;
+   if (!wd) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+   if (ev->button != 1) return;
+   //   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+   if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
+   wd->longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
+   wd->downx = ev->canvas.x;
+   wd->downy = ev->canvas.y;
+}
+
+static void
+_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Up *ev = event_info;
+   if (!wd) return;
+   if (ev->button != 1) return;
+   if (wd->longpress_timer)
+     {
+       ecore_timer_del(wd->longpress_timer);
+       wd->longpress_timer = NULL;
+     }
+}
+
+static void
+_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Move *ev = event_info;
+   if (!wd) return;
+   if (!wd->selmode)
+     {
+       if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+         {
+            if (wd->longpress_timer)
+              {
+                 ecore_timer_del(wd->longpress_timer);
+                 wd->longpress_timer = NULL;
+              }
+         }
+       else if (wd->longpress_timer)
+         {
+            Evas_Coord dx, dy;
+
+            dx = wd->downx - ev->cur.canvas.x;
+            dx *= dx;
+            dy = wd->downy - ev->cur.canvas.y;
+            dy *= dy;
+            if ((dx + dy) >
+                ((_elm_config->finger_size / 2) *
+                 (_elm_config->finger_size / 2)))
+              {
+                 ecore_timer_del(wd->longpress_timer);
+                 wd->longpress_timer = NULL;
+              }
+         }
+     }
+   else if (wd->longpress_timer)
+     {
+       Evas_Coord dx, dy;
+
+       dx = wd->downx - ev->cur.canvas.x;
+       dx *= dx;
+       dy = wd->downy - ev->cur.canvas.y;
+       dy *= dy;
+       if ((dx + dy) >
+           ((_elm_config->finger_size / 2) *
+            (_elm_config->finger_size / 2)))
+         {
+            ecore_timer_del(wd->longpress_timer);
+            wd->longpress_timer = NULL;
+         }
+     }
+}
+
+static const char *
+_getbase(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return "base";
+   if (wd->editable)
+     {
+       if (wd->password) return "base-password";
+       else
+         {
+            if (wd->single_line) return "base-single";
+            else
+              {
+                 if (wd->linewrap) return "base";
+                  else if (wd->char_linewrap) return "base-charwrap";
+                 else  return "base-nowrap";
+              }
+         }
+     }
+   else
+     {
+       if (wd->password) return "base-password";
+       else
+         {
+            if (wd->single_line) return "base-single-noedit";
+            else
+              {
+                 if (wd->linewrap) return "base-noedit";
+                  else if (wd->char_linewrap) return "base-noedit-charwrap";
+                 else  return "base-nowrap-noedit";
+              }
+         }
+     }
+   return "base";
+}
+
+static void
+_signal_entry_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->changed = EINA_TRUE;
+   _sizing_eval(data);
+   if (wd->text) eina_stringshare_del(wd->text);
+   wd->text = NULL;
+   evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
+   if (wd->delay_write)
+     {
+       ecore_timer_del(wd->delay_write);
+       wd->delay_write = NULL;
+     }
+   if ((!wd->autosave) || (!wd->file)) return;
+   wd->delay_write = ecore_timer_add(2.0, _delay_write, data);
+}
+
+static void
+_signal_selection_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   const Eina_List *l;
+   Evas_Object *entry;
+   if (!wd) return;
+   EINA_LIST_FOREACH(entries, l, entry)
+     {
+       if (entry != data) elm_entry_select_none(entry);
+     }
+   wd->have_selection = EINA_TRUE;
+   evas_object_smart_callback_call(data, SIG_SELECTION_START, NULL);
+#ifdef HAVE_ELEMENTARY_X
+   if (wd->sel_notify_handler)
+     {
+       const char *txt = elm_entry_selection_get(data);
+       Evas_Object *top;
+
+       top = elm_widget_top_get(data);
+       if ((top) && (elm_win_xwindow_get(top)))
+            elm_selection_set(ELM_SEL_PRIMARY, data, ELM_SEL_FORMAT_MARKUP, txt);
+     }
+#endif
+}
+
+static void
+_signal_selection_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->have_selection = EINA_TRUE;
+   evas_object_smart_callback_call(data, SIG_SELECTION_CHANGED, NULL);
+   elm_selection_set(ELM_SEL_PRIMARY, obj, ELM_SEL_FORMAT_MARKUP,
+                  elm_entry_selection_get(data));
+}
+
+static void
+_signal_selection_cleared(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (!wd->have_selection) return;
+   wd->have_selection = EINA_FALSE;
+   evas_object_smart_callback_call(data, SIG_SELECTION_CLEARED, NULL);
+   if (wd->sel_notify_handler)
+     {
+       if (wd->cut_sel)
+         {
+#ifdef HAVE_ELEMENTARY_X
+            Evas_Object *top;
+
+            top = elm_widget_top_get(data);
+            if ((top) && (elm_win_xwindow_get(top)))
+                elm_selection_set(ELM_SEL_PRIMARY, data, ELM_SEL_FORMAT_MARKUP,
+                                      wd->cut_sel);
+#endif
+            eina_stringshare_del(wd->cut_sel);
+            wd->cut_sel = NULL;
+         }
+       else
+         {
+#ifdef HAVE_ELEMENTARY_X
+            Evas_Object *top;
+
+            top = elm_widget_top_get(data);
+            if ((top) && (elm_win_xwindow_get(top)))
+               elm_selection_clear(ELM_SEL_PRIMARY, data);
+#endif
+         }
+     }
+}
+
+static void
+_signal_entry_paste_request(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
+   if (wd->sel_notify_handler)
+     {
+#ifdef HAVE_ELEMENTARY_X
+       Evas_Object *top;
+
+       top = elm_widget_top_get(data);
+       if ((top) && (elm_win_xwindow_get(top)))
+         {
+             wd->selection_asked = EINA_TRUE;
+             elm_selection_get(ELM_SEL_CLIPBOARD, ELM_SEL_FORMAT_MARKUP, data,
+                               NULL, NULL);
+         }
+#endif
+     }
+}
+
+static void
+_signal_entry_copy_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_SELECTION_COPY, NULL);
+   elm_selection_set(ELM_SEL_CLIPBOARD, obj, ELM_SEL_FORMAT_MARKUP,
+                       elm_entry_selection_get(data));
+}
+
+static void
+_signal_entry_cut_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_SELECTION_CUT, NULL);
+   elm_selection_set(ELM_SEL_CLIPBOARD, obj, ELM_SEL_FORMAT_MARKUP,
+                       elm_entry_selection_get(data));
+   edje_object_part_text_insert(wd->ent, "elm.text", "");
+   wd->changed = EINA_TRUE;
+   _sizing_eval(data);
+}
+
+static void
+_signal_cursor_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord cx, cy, cw, ch;
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_CURSOR_CHANGED, NULL);
+   edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
+                                             &cx, &cy, &cw, &ch);
+   if (!wd->deferred_recalc_job)
+     elm_widget_show_region_set(data, cx, cy, cw, ch);
+   else
+     {
+       wd->deferred_cur = EINA_TRUE;
+       wd->cx = cx;
+       wd->cy = cy;
+       wd->cw = cw;
+       wd->ch = ch;
+     }
+}
+
+static void
+_signal_anchor_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+}
+
+static void
+_signal_anchor_up(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Elm_Entry_Anchor_Info ei;
+   char *buf2, *p, *p2, *n;
+   if (!wd) return;
+   p = strrchr(emission, ',');
+   if (p)
+     {
+       const Eina_List *geoms;
+
+       n = p + 1;
+       p2 = p -1;
+       while (p2 >= emission)
+         {
+            if (*p2 == ',') break;
+            p2--;
+         }
+       p2++;
+       buf2 = alloca(5 + p - p2);
+       strncpy(buf2, p2, p - p2);
+       buf2[p - p2] = 0;
+       ei.name = n;
+       ei.button = atoi(buf2);
+       ei.x = ei.y = ei.w = ei.h = 0;
+       geoms =
+          edje_object_part_text_anchor_geometry_get(wd->ent, "elm.text", ei.name);
+       if (geoms)
+         {
+            Evas_Textblock_Rectangle *r;
+            const Eina_List *l;
+            Evas_Coord px, py, x, y;
+
+            evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
+            evas_pointer_output_xy_get(evas_object_evas_get(wd->ent), &px, &py);
+            EINA_LIST_FOREACH(geoms, l, r)
+              {
+                 if (((r->x + x) <= px) && ((r->y + y) <= py) &&
+                     ((r->x + x + r->w) > px) && ((r->y + y + r->h) > py))
+                   {
+                      ei.x = r->x + x;
+                      ei.y = r->y + y;
+                      ei.w = r->w;
+                      ei.h = r->h;
+                      break;
+                   }
+              }
+         }
+       if (!wd->disabled)
+         evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, &ei);
+     }
+}
+
+static void
+_signal_anchor_move(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+}
+
+static void
+_signal_anchor_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+}
+
+static void
+_signal_anchor_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+}
+
+static void
+_signal_key_enter(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_ACTIVATED, NULL);
+}
+
+static void
+_signal_mouse_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_PRESS, NULL);
+}
+
+static void
+_signal_mouse_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
+}
+
+static void
+_signal_mouse_double(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
+}
+
+#ifdef HAVE_ELEMENTARY_X
+static Eina_Bool
+_event_selection_notify(void *data, int type __UNUSED__, void *event)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Ecore_X_Event_Selection_Notify *ev = event;
+   if (!wd) return ECORE_CALLBACK_PASS_ON;
+   if ((!wd->selection_asked) && (!wd->drag_selection_asked))
+      return ECORE_CALLBACK_PASS_ON;
+
+   if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
+       (ev->selection == ECORE_X_SELECTION_PRIMARY))
+     {
+       Ecore_X_Selection_Data_Text *text_data;
+
+       text_data = ev->data;
+       if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
+         {
+            if (text_data->text)
+              {
+                 char *txt = _elm_util_text_to_mkup(text_data->text);
+
+                 if (txt)
+                   {
+                      elm_entry_entry_insert(data, txt);
+                      free(txt);
+                   }
+              }
+         }
+       wd->selection_asked = EINA_FALSE;
+     }
+   else if (ev->selection == ECORE_X_SELECTION_XDND)
+     {
+       Ecore_X_Selection_Data_Text *text_data;
+
+       text_data = ev->data;
+       if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
+         {
+            if (text_data->text)
+              {
+                 char *txt = _elm_util_text_to_mkup(text_data->text);
+
+                 if (txt)
+                   {
+                     /* Massive FIXME: this should be at the drag point */
+                      elm_entry_entry_insert(data, txt);
+                      free(txt);
+                   }
+              }
+         }
+       wd->drag_selection_asked = EINA_FALSE;
+
+        ecore_x_dnd_send_finished();
+
+     }
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_event_selection_clear(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
+{
+/*
+   Widget_Data *wd = elm_widget_data_get(data);
+   Ecore_X_Event_Selection_Clear *ev = event;
+   if (!wd) return ECORE_CALLBACK_PASS_ON;
+   if (!wd->have_selection) return ECORE_CALLBACK_PASS_ON;
+   if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
+       (ev->selection == ECORE_X_SELECTION_PRIMARY))
+     {
+       elm_entry_select_none(data);
+     }
+   return 1;*/
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+
+static Eina_Bool
+_drag_drop_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Selection_Data *drop)
+{
+   Widget_Data *wd;
+   Eina_Bool rv;
+
+   wd = elm_widget_data_get(obj);
+
+   if (!wd) return EINA_FALSE;
+   printf("Inserting at (%d,%d) %s\n",drop->x,drop->y,(char*)drop->data);
+
+   edje_object_part_text_cursor_copy(wd->ent, "elm.text",
+                                     EDJE_CURSOR_MAIN,/*->*/EDJE_CURSOR_USER);
+   rv = edje_object_part_text_cursor_coord_set(wd->ent,"elm.text",
+                                          EDJE_CURSOR_MAIN,drop->x,drop->y);
+   if (!rv) printf("Warning: Failed to position cursor: paste anyway\n");
+   elm_entry_entry_insert(obj, drop->data);
+   edje_object_part_text_cursor_copy(wd->ent, "elm.text",
+                                     EDJE_CURSOR_USER,/*->*/EDJE_CURSOR_MAIN);
+
+   return EINA_TRUE;
+}
+#endif
+
+static Evas_Object *
+_get_item(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, const char *item)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Object *o;
+   Eina_List *l;
+   Elm_Entry_Item_Provider *ip;
+
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        o = ip->func(ip->data, data, item);
+        if (o) return o;
+     }
+   if (!strncmp(item, "file://", 7))
+     {
+        const char *fname = item + 7;
+       
+        o = evas_object_image_filled_add(evas_object_evas_get(data));
+        evas_object_image_file_set(o, fname, NULL);
+        if (evas_object_image_load_error_get(o) == EVAS_LOAD_ERROR_NONE)
+          {
+             evas_object_show(o);
+          }
+        else
+          {
+             evas_object_del(o);
+             o = edje_object_add(evas_object_evas_get(data));
+             _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
+          }
+        return o;
+     }
+   o = edje_object_add(evas_object_evas_get(data));
+   if (!_elm_theme_object_set(data, o, "entry", item, elm_widget_style_get(data)))
+     _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
+   return o;
+}
+
+static void
+_text_filter(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, Edje_Text_Filter_Type type, char **text)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Eina_List *l;
+   Elm_Entry_Text_Filter *tf;
+
+   if (type == EDJE_TEXT_FILTER_FORMAT)
+     return;
+
+   EINA_LIST_FOREACH(wd->text_filters, l, tf)
+     {
+        tf->func(tf->data, data, text);
+        if (!*text)
+           break;
+     }
+}
+
+/**
+ * This adds an entry to @p parent object.
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Entry
+ */
+EAPI Evas_Object *
+elm_entry_add(Evas_Object *parent)
+{
+   Evas_Object *obj, *top;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "entry");
+   elm_widget_type_set(obj, "entry");
+   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_del_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_on_focus_region_hook_set(obj, _on_focus_region_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_object_cursor_set(obj, ELM_CURSOR_XTERM);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_highlight_ignore_set(obj, EINA_TRUE);
+
+   wd->linewrap     = EINA_TRUE;
+   wd->char_linewrap= EINA_FALSE;
+   wd->editable     = EINA_TRUE;
+   wd->disabled     = EINA_FALSE;
+   wd->context_menu = EINA_TRUE;
+   wd->autosave     = EINA_TRUE;
+   wd->textonly     = EINA_FALSE;
+
+   wd->ent = edje_object_add(e);
+   edje_object_item_provider_set(wd->ent, _get_item, obj);
+   edje_object_text_insert_filter_callback_add(wd->ent,"elm.text", _text_filter, obj);
+   evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOVE, _move, obj);
+   evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_RESIZE, _resize, obj);
+   evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _mouse_down, obj);
+   evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_UP,
+                                  _mouse_up, obj);
+   evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _mouse_move, obj);
+
+   _elm_theme_object_set(obj, wd->ent, "entry", "base", "default");
+   edje_object_signal_callback_add(wd->ent, "entry,changed", "elm.text",
+                                   _signal_entry_changed, obj);
+   edje_object_signal_callback_add(wd->ent, "selection,start", "elm.text",
+                                   _signal_selection_start, obj);
+   edje_object_signal_callback_add(wd->ent, "selection,changed", "elm.text",
+                                   _signal_selection_changed, obj);
+   edje_object_signal_callback_add(wd->ent, "selection,cleared", "elm.text",
+                                   _signal_selection_cleared, obj);
+   edje_object_signal_callback_add(wd->ent, "entry,paste,request", "elm.text",
+                                   _signal_entry_paste_request, obj);
+   edje_object_signal_callback_add(wd->ent, "entry,copy,notify", "elm.text",
+                                   _signal_entry_copy_notify, obj);
+   edje_object_signal_callback_add(wd->ent, "entry,cut,notify", "elm.text",
+                                   _signal_entry_cut_notify, obj);
+   edje_object_signal_callback_add(wd->ent, "cursor,changed", "elm.text",
+                                   _signal_cursor_changed, obj);
+   edje_object_signal_callback_add(wd->ent, "anchor,mouse,down,*", "elm.text",
+                                   _signal_anchor_down, obj);
+   edje_object_signal_callback_add(wd->ent, "anchor,mouse,up,*", "elm.text",
+                                   _signal_anchor_up, obj);
+   edje_object_signal_callback_add(wd->ent, "anchor,mouse,move,*", "elm.text",
+                                   _signal_anchor_move, obj);
+   edje_object_signal_callback_add(wd->ent, "anchor,mouse,in,*", "elm.text",
+                                   _signal_anchor_in, obj);
+   edje_object_signal_callback_add(wd->ent, "anchor,mouse,out,*", "elm.text",
+                                   _signal_anchor_out, obj);
+   edje_object_signal_callback_add(wd->ent, "entry,key,enter", "elm.text",
+                                   _signal_key_enter, obj);
+   edje_object_signal_callback_add(wd->ent, "mouse,down,1", "elm.text",
+                                   _signal_mouse_down, obj);
+   edje_object_signal_callback_add(wd->ent, "mouse,clicked,1", "elm.text",
+                                   _signal_mouse_clicked, obj);
+   edje_object_signal_callback_add(wd->ent, "mouse,down,1,double", "elm.text",
+                                   _signal_mouse_double, obj);
+   edje_object_part_text_set(wd->ent, "elm.text", "");
+   elm_widget_resize_object_set(obj, wd->ent);
+   _sizing_eval(obj);
+
+#ifdef HAVE_ELEMENTARY_X
+   top = elm_widget_top_get(obj);
+   if ((top) && (elm_win_xwindow_get(top)))
+     {
+       wd->sel_notify_handler =
+         ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,
+                                 _event_selection_notify, obj);
+       wd->sel_clear_handler =
+         ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR,
+                                 _event_selection_clear, obj);
+     }
+
+   elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE,
+                  _drag_drop_cb, NULL);
+#endif
+
+   entries = eina_list_prepend(entries, obj);
+
+   // module - find module for entry
+   wd->api = _module(obj);
+   // if found - hook in
+   if ((wd->api) && (wd->api->obj_hook)) wd->api->obj_hook(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+
+/**
+ * This sets the entry object not to line wrap.  All input will
+ * be on a single line, and the entry box will extend with user input.
+ *
+ * @param obj The entry object
+ * @param single_line If true, the text in the entry
+ * will be on a single line.
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *t;
+   if (!wd) return;
+   if (wd->single_line == single_line) return;
+   wd->single_line = single_line;
+   wd->linewrap = EINA_FALSE;
+   wd->char_linewrap = EINA_FALSE;
+   elm_entry_cnp_textonly_set(obj, EINA_TRUE);
+   t = eina_stringshare_add(elm_entry_entry_get(obj));
+   _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
+   elm_entry_entry_set(obj, t);
+   eina_stringshare_del(t);
+   _sizing_eval(obj);
+}
+
+/**
+ * This returns true if the entry has been set to single line mode.
+ * See also elm_entry_single_line_set().
+ *
+ * @param obj The entry object
+ * @return single_line If true, the text in the entry is set to display
+ * on a single line.
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_single_line_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->single_line;
+}
+
+/**
+ * This sets the entry object to password mode.  All text entered
+ * and/or displayed within the widget will be replaced with asterisks (*).
+ *
+ * @param obj The entry object
+ * @param password If true, password mode is enabled.
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_password_set(Evas_Object *obj, Eina_Bool password)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *t;
+   if (!wd) return;
+   if (wd->password == password) return;
+   wd->password = password;
+   wd->single_line = EINA_TRUE;
+   wd->linewrap = EINA_FALSE;
+   wd->char_linewrap = EINA_FALSE;
+   t = eina_stringshare_add(elm_entry_entry_get(obj));
+   _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
+   elm_entry_entry_set(obj, t);
+   eina_stringshare_del(t);
+   _sizing_eval(obj);
+}
+
+
+/**
+ * This returns whether password mode is enabled.
+ * See also elm_entry_password_set().
+ *
+ * @param obj The entry object
+ * @return If true, the entry is set to display all characters
+ * as asterisks (*).
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_password_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->password;
+}
+
+/**
+ * This sets the text displayed within the entry to @p entry.
+ *
+ * @param obj The entry object
+ * @param entry The text to be displayed
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_entry_set(Evas_Object *obj, const char *entry)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (!entry) entry = "";
+   edje_object_part_text_set(wd->ent, "elm.text", entry);
+   if (wd->text) eina_stringshare_del(wd->text);
+   wd->text = NULL;
+   wd->changed = EINA_TRUE;
+   _sizing_eval(obj);
+}
+
+/**
+ * This returns the text currently shown in object @p entry.
+ * See also elm_entry_entry_set().
+ *
+ * @param obj The entry object
+ * @return The currently displayed text or NULL on failure
+ *
+ * @ingroup Entry
+ */
+EAPI const char *
+elm_entry_entry_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *text;
+   if (!wd) return NULL;
+   if (wd->text) return wd->text;
+   text = edje_object_part_text_get(wd->ent, "elm.text");
+   if (!text)
+     {
+       ERR("text=NULL for edje %p, part 'elm.text'", wd->ent);
+       return NULL;
+     }
+   eina_stringshare_replace(&wd->text, text);
+   return wd->text;
+}
+
+
+/**
+ * This returns EINA_TRUE if the entry is empty/there was an error
+ * and EINA_FALSE if it is not empty.
+ *
+ * @param obj The entry object
+ * @return If the entry is empty or not.
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_is_empty(const Evas_Object *obj)
+{
+   /* FIXME: until there's support for that in textblock, we just check
+    * to see if the there is text or not. */
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Evas_Object *tb;
+   Evas_Textblock_Cursor *cur;
+   Eina_Bool ret;
+   if (!wd) return EINA_TRUE;
+   /* It's a hack until we get the support suggested above.
+    * We just create a cursor, point it to the begining, and then
+    * try to advance it, if it can advance, the tb is not empty,
+    * otherwise it is. */
+   tb = edje_object_part_object_get(wd->ent, "elm.text");
+   cur = evas_object_textblock_cursor_new((Evas_Object *) tb); /* This is
+      actually, ok for the time being, thsese hackish stuff will be removed
+      once evas 1.0 is out*/
+   evas_textblock_cursor_pos_set(cur, 0);
+   ret = evas_textblock_cursor_char_next(cur);
+   evas_textblock_cursor_free(cur);
+
+   return !ret;
+}
+
+/**
+ * This returns all selected text within the entry.
+ *
+ * @param obj The entry object
+ * @return The selected text within the entry or NULL on failure
+ *
+ * @ingroup Entry
+ */
+EAPI const char *
+elm_entry_selection_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return edje_object_part_text_selection_get(wd->ent, "elm.text");
+}
+
+/**
+ * This inserts text in @p entry where the current cursor position.
+ * 
+ * This inserts text at the cursor position is as if it was typed 
+ * by the user (note this also allows markup which a user
+ * can't just "type" as it would be converted to escaped text, so this
+ * call can be used to insert things like emoticon items or bold push/pop
+ * tags, other font and color change tags etc.)
+ *
+ * @param obj The entry object
+ * @param entry The text to insert
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_entry_insert(Evas_Object *obj, const char *entry)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_part_text_insert(wd->ent, "elm.text", entry);
+   wd->changed = EINA_TRUE;
+   _sizing_eval(obj);
+}
+
+/**
+ * This enables word line wrapping in the entry object.  It is the opposite
+ * of elm_entry_single_line_set().  Additionally, setting this disables
+ * character line wrapping.
+ * See also elm_entry_line_char_wrap_set().
+ *
+ * @param obj The entry object
+ * @param wrap If true, the entry will be wrapped once it reaches the end
+ * of the object. Wrapping will occur at the end of the word before the end of the
+ * object.
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_line_wrap_set(Evas_Object *obj, Eina_Bool wrap)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *t;
+   if (!wd) return;
+   if (wd->linewrap == wrap) return;
+   wd->linewrap = wrap;
+   if(wd->linewrap)
+       wd->char_linewrap = EINA_FALSE;
+   t = eina_stringshare_add(elm_entry_entry_get(obj));
+   _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
+   elm_entry_entry_set(obj, t);
+   eina_stringshare_del(t);
+   _sizing_eval(obj);
+}
+
+/**
+ * This enables character line wrapping in the entry object.  It is the opposite
+ * of elm_entry_single_line_set().  Additionally, setting this disables
+ * word line wrapping.
+ * See also elm_entry_line_wrap_set().
+ *
+ * @param obj The entry object
+ * @param wrap If true, the entry will be wrapped once it reaches the end
+ * of the object. Wrapping will occur immediately upon reaching the end of the object.
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_line_char_wrap_set(Evas_Object *obj, Eina_Bool wrap)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *t;
+   if (!wd) return;
+   if (wd->char_linewrap == wrap) return;
+   wd->char_linewrap = wrap;
+   if(wd->char_linewrap)
+       wd->linewrap = EINA_FALSE;
+   t = eina_stringshare_add(elm_entry_entry_get(obj));
+   _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
+   elm_entry_entry_set(obj, t);
+   eina_stringshare_del(t);
+   _sizing_eval(obj);
+}
+
+/**
+ * This sets the editable attribute of the entry.
+ *
+ * @param obj The entry object
+ * @param editable If true, the entry will be editable by the user.
+ * If false, it will be set to the disabled state.
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_editable_set(Evas_Object *obj, Eina_Bool editable)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *t;
+   if (!wd) return;
+   if (wd->editable == editable) return;
+   wd->editable = editable;
+   t = eina_stringshare_add(elm_entry_entry_get(obj));
+   _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
+   elm_entry_entry_set(obj, t);
+   eina_stringshare_del(t);
+   _sizing_eval(obj);
+
+#ifdef HAVE_ELEMENTARY_X
+   if (editable)
+      elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP, _drag_drop_cb, NULL);
+   else
+      elm_drop_target_del(obj);
+#endif
+}
+
+/**
+ * This gets the editable attribute of the entry.
+ * See also elm_entry_editable_set().
+ *
+ * @param obj The entry object
+ * @return If true, the entry is editable by the user.
+ * If false, it is not editable by the user
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_editable_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->editable;
+}
+
+/**
+ * This drops any existing text selection within the entry.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_select_none(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->selmode)
+     {
+       wd->selmode = EINA_FALSE;
+       edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
+       edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
+     }
+   wd->have_selection = EINA_FALSE;
+   edje_object_part_text_select_none(wd->ent, "elm.text");
+}
+
+/**
+ * This selects all text within the entry.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_select_all(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->selmode)
+     {
+       wd->selmode = EINA_FALSE;
+       edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
+       edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
+     }
+   wd->have_selection = EINA_TRUE;
+   edje_object_part_text_select_all(wd->ent, "elm.text");
+}
+
+/**
+ * This function returns the geometry of the cursor.
+ *
+ * It's useful if you want to draw something on the cursor (or where it is),
+ * or for example in the case of scrolled entry where you want to show the
+ * cursor.
+ *
+ * @param obj The entry object
+ * @param x returned geometry
+ * @param y returned geometry
+ * @param w returned geometry
+ * @param h returned geometry
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cursor_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
+   return EINA_TRUE;
+}
+
+/**
+ * This moves the cursor one place to the right within the entry.
+ *
+ * @param obj The entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cursor_next(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return edje_object_part_text_cursor_next(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This moves the cursor one place to the left within the entry.
+ *
+ * @param obj The entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cursor_prev(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return edje_object_part_text_cursor_prev(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This moves the cursor one line up within the entry.
+ *
+ * @param obj The entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cursor_up(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return edje_object_part_text_cursor_up(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This moves the cursor one line down within the entry.
+ *
+ * @param obj The entry object
+ * @return EINA_TRUE upon success, EINA_FALSE upon failure
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cursor_down(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return edje_object_part_text_cursor_down(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This moves the cursor to the beginning of the entry.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_cursor_begin_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_part_text_cursor_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This moves the cursor to the end of the entry.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_cursor_end_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_part_text_cursor_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This moves the cursor to the beginning of the current line.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_cursor_line_begin_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_part_text_cursor_line_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This moves the cursor to the end of the current line.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_cursor_line_end_set(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_part_text_cursor_line_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This begins a selection within the entry as though
+ * the user were holding down the mouse button to make a selection.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_cursor_selection_begin(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_part_text_select_begin(wd->ent, "elm.text");
+}
+
+/**
+ * This ends a selection within the entry as though
+ * the user had just released the mouse button while making a selection.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_cursor_selection_end(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_part_text_select_extend(wd->ent, "elm.text");
+}
+
+/**
+ * TODO: fill this in
+ *
+ * @param obj The entry object
+ * @return TODO: fill this in
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cursor_is_format_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 edje_object_part_text_cursor_is_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This returns whether the cursor is visible.
+ *
+ * @param obj The entry object
+ * @return If true, the cursor is visible.
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cursor_is_visible_format_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 edje_object_part_text_cursor_is_visible_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * TODO: fill this in
+ *
+ * @param obj The entry object
+ * @return TODO: fill this in
+ *
+ * @ingroup Entry
+ */
+EAPI const char *
+elm_entry_cursor_content_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return edje_object_part_text_cursor_content_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
+}
+
+/**
+ * This executes a "cut" action on the selected text in the entry.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_selection_cut(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _cut(obj, NULL, NULL);
+}
+
+/**
+ * This executes a "copy" action on the selected text in the entry.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_selection_copy(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _copy(obj, NULL, NULL);
+}
+
+/**
+ * This executes a "paste" action in the entry.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_selection_paste(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _paste(obj, NULL, NULL);
+}
+
+/**
+ * This clears and frees the items in a entry's contextual (right click) menu.
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_context_menu_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Entry_Context_Menu_Item *it;
+   if (!wd) return;
+   EINA_LIST_FREE(wd->items, it)
+     {
+        eina_stringshare_del(it->label);
+        eina_stringshare_del(it->icon_file);
+        eina_stringshare_del(it->icon_group);
+        free(it);
+     }
+}
+
+/**
+ * This adds an item to the entry's contextual menu.
+ *
+ * @param obj The entry object
+ * @param label The item's text label
+ * @param icon_file The item's icon file
+ * @param icon_type The item's icon type
+ * @param func The callback to execute when the item is clicked
+ * @param data The data to associate with the item for related functions
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_context_menu_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Entry_Context_Menu_Item *it;
+   if (!wd) return;
+   it = calloc(1, sizeof(Elm_Entry_Context_Menu_Item));
+   if (!it) return;
+   wd->items = eina_list_append(wd->items, it);
+   it->obj = obj;
+   it->label = eina_stringshare_add(label);
+   it->icon_file = eina_stringshare_add(icon_file);
+   it->icon_type = icon_type;
+   it->func = func;
+   it->data = (void *)data;
+}
+
+/**
+ * This disables the entry's contextual (right click) menu.
+ *
+ * @param obj The entry object
+ * @param disabled If true, the menu is disabled
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->context_menu == !disabled) return;
+   wd->context_menu = !disabled;
+}
+
+/**
+ * This returns whether the entry's contextual (right click) menu is disabled.
+ *
+ * @param obj The entry object
+ * @return If true, the menu is disabled
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_context_menu_disabled_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->context_menu;
+}
+
+/**
+ * This appends a custom item provider to the list for that entry
+ *
+ * This appends the given callback. The list is walked from beginning to end
+ * with each function called given the item href string in the text. If the
+ * function returns an object handle other than NULL (it should create an
+ * and object to do this), then this object is used to replace that item. If
+ * not the next provider is called until one provides an item object, or the
+ * default provider in entry does.
+ * 
+ * @param obj The entry object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_append(wd->item_providers, ip);
+}
+
+/**
+ * This prepends a custom item provider to the list for that entry
+ *
+ * This prepends the given callback. See elm_entry_item_provider_append() for
+ * more information
+ * 
+ * @param obj The entry object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
+   if (!ip) return;
+   ip->func = func;
+   ip->data = data;
+   wd->item_providers = eina_list_prepend(wd->item_providers, ip);
+}
+
+/**
+ * This removes a custom item provider to the list for that entry
+ *
+ * This removes the given callback. See elm_entry_item_provider_append() for
+ * more information
+ * 
+ * @param obj The entry object
+ * @param func The function called to provide the item object
+ * @param data The data passed to @p func
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Entry_Item_Provider *ip;
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   EINA_LIST_FOREACH(wd->item_providers, l, ip)
+     {
+        if ((ip->func == func) && (ip->data == data))
+          {
+             wd->item_providers = eina_list_remove_list(wd->item_providers, l);
+             free(ip);
+             return;
+          }
+     }
+}
+
+/**
+ * Append a filter function for text inserted in the entry
+ *
+ * Append the given callback to the list. This functions will be called
+ * whenever any text is inserted into the entry, with the text to be inserted
+ * as a parameter. The callback function is free to alter the text in any way
+ * it wants, but it must remember to free the given pointer and update it.
+ * If the new text is to be discarded, the function can free it and set it text
+ * parameter to NULL. This will also prevent any following filters from being
+ * called.
+ *
+ * @param obj The entry object
+ * @param func The function to use as text filter
+ * @param data User data to pass to @p func
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
+{
+   Widget_Data *wd;
+   Elm_Entry_Text_Filter *tf;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   wd = elm_widget_data_get(obj);
+
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   tf = ELM_NEW(Elm_Entry_Text_Filter);
+   if (!tf) return;
+   tf->func = func;
+   tf->data = data;
+   wd->text_filters = eina_list_append(wd->text_filters, tf);
+}
+
+/**
+ * Prepend a filter function for text insdrted in the entry
+ *
+ * Prepend the given callback to the list. See elm_entry_text_filter_append()
+ * for more information
+ *
+ * @param obj The entry object
+ * @param func The function to use as text filter
+ * @param data User data to pass to @p func
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
+{
+   Widget_Data *wd;
+   Elm_Entry_Text_Filter *tf;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   wd = elm_widget_data_get(obj);
+
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   tf = ELM_NEW(Elm_Entry_Text_Filter);
+   if (!tf) return;
+   tf->func = func;
+   tf->data = data;
+   wd->text_filters = eina_list_prepend(wd->text_filters, tf);
+}
+
+/**
+ * Remove a filter from the list
+ *
+ * Removes the given callback from the filter list. See elm_entry_text_filter_append()
+ * for more information.
+ *
+ * @param obj The entry object
+ * @param func The filter function to remove
+ * @param data The user data passed when adding the function
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
+{
+   Widget_Data *wd;
+   Eina_List *l;
+   Elm_Entry_Text_Filter *tf;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   wd = elm_widget_data_get(obj);
+
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   EINA_LIST_FOREACH(wd->text_filters, l, tf)
+     {
+        if ((tf->func == func) && (tf->data == data))
+          {
+             wd->text_filters = eina_list_remove_list(wd->text_filters, l);
+             free(tf);
+             return;
+          }
+     }
+}
+
+/**
+ * This converts a markup (HTML-like) string into UTF-8.
+ *
+ * @param s The string (in markup) to be converted
+ * @return The converted string (in UTF-8)
+ *
+ * @ingroup Entry
+ */
+EAPI char *
+elm_entry_markup_to_utf8(const char *s)
+{
+   char *ss = _elm_util_mkup_to_text(s);
+   if (!ss) ss = strdup("");
+   return ss;
+}
+
+/**
+ * This converts a UTF-8 string into markup (HTML-like).
+ *
+ * @param s The string (in UTF-8) to be converted
+ * @return The converted string (in markup)
+ *
+ * @ingroup Entry
+ */
+EAPI char *
+elm_entry_utf8_to_markup(const char *s)
+{
+   char *ss = _elm_util_text_to_mkup(s);
+   if (!ss) ss = strdup("");
+   return ss;
+}
+
+/**
+ * Filter inserted text based on user defined character and byte limits
+ *
+ * Add this filter to an entry to limit the characters that it will accept
+ * based the the contents of the provided Elm_Entry_Filter_Limit_Size.
+ * The funtion works on the UTF-8 representation of the string, converting
+ * it from the set markup, thus not accounting for any format in it.
+ *
+ * The user must create an Elm_Entry_Filter_Limit_Size structure and pass
+ * it as data when setting the filter. In it it's possible to set limits
+ * by character count or bytes (any of them is disabled if 0), and both can
+ * be set at the same time. In that case, it first checks for characters,
+ * then bytes.
+ *
+ * The function will cut the inserted text in order to allow only the first
+ * number of characters that are still allowed. The cut is made in
+ * characters, even when limiting by bytes, in order to always contain
+ * valid ones and avoid half unicode characters making it in.
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text)
+{
+   Elm_Entry_Filter_Limit_Size *lim = data;
+   char *current;
+   int len, newlen;
+   const char *(*text_get)(const Evas_Object *);
+   const char *widget_type;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(entry);
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   /* hack. I don't want to copy the entire function to work with
+    * scrolled_entry */
+   widget_type = elm_widget_type_get(entry);
+   if (!strcmp(widget_type, "entry"))
+      text_get = elm_entry_entry_get;
+   else if (!strcmp(widget_type, "scrolled_entry"))
+      text_get = elm_scrolled_entry_entry_get;
+   else /* huh? */
+      return;
+
+   current = elm_entry_markup_to_utf8(text_get(entry));
+
+   if (lim->max_char_count > 0)
+     {
+        int cut;
+        len = evas_string_char_len_get(current);
+        if (len >= lim->max_char_count)
+          {
+             free(*text);
+             free(current);
+             *text = NULL;
+             return;
+          }
+        newlen = evas_string_char_len_get(*text);
+        cut = strlen(*text);
+        while ((len + newlen) > lim->max_char_count)
+          {
+             cut = evas_string_char_prev_get(*text, cut, NULL);
+             newlen--;
+          }
+        (*text)[cut] = 0;
+     }
+
+   if (lim->max_byte_count > 0)
+     {
+        len = strlen(current);
+        if (len >= lim->max_byte_count)
+          {
+             free(*text);
+             free(current);
+             *text = NULL;
+             return;
+          }
+        newlen = strlen(*text);
+        while ((len + newlen) > lim->max_byte_count)
+          {
+             int p = evas_string_char_prev_get(*text, newlen, NULL);
+             newlen -= (newlen - p);
+          }
+        if (newlen)
+           (*text)[newlen] = 0;
+        else
+          {
+             free(*text);
+             *text = NULL;
+          }
+     }
+   free(current);
+}
+
+/**
+ * Filter inserted text based on accepted or rejected sets of characters
+ *
+ * Add this filter to an entry to restrict the set of accepted characters
+ * based on the sets in the provided Elm_Entry_Filter_Accept_Set.
+ * This structure contains both accepted and rejected sets, but they are
+ * mutually exclusive. If accepted is set, it will be used, otherwise it
+ * goes on to the rejected set.
+ */
+EAPI void
+elm_entry_filter_accept_set(void *data, Evas_Object *entry __UNUSED__, char **text)
+{
+   Elm_Entry_Filter_Accept_Set *as = data;
+   const char *set;
+   char *insert;
+   Eina_Bool goes_in;
+   int read_idx, last_read_idx = 0, read_char;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   if ((!as->accepted) && (!as->rejected))
+      return;
+
+   if (as->accepted)
+     {
+        set = as->accepted;
+        goes_in = EINA_TRUE;
+     }
+   else
+     {
+        set = as->rejected;
+        goes_in = EINA_FALSE;
+     }
+
+   insert = *text;
+   read_idx = evas_string_char_next_get(*text, 0, &read_char);
+   while (read_char)
+     {
+        int cmp_idx, cmp_char;
+        Eina_Bool in_set = EINA_FALSE;
+
+        cmp_idx = evas_string_char_next_get(set, 0, &cmp_char);
+        while (cmp_char)
+          {
+             if (read_char == cmp_char)
+               {
+                  in_set = EINA_TRUE;
+                  break;
+               }
+             cmp_idx = evas_string_char_next_get(set, cmp_idx, &cmp_char);
+          }
+        if (in_set == goes_in)
+          {
+             int size = read_idx - last_read_idx;
+             const char *src = (*text) + last_read_idx;
+             if (src != insert)
+                memcpy(insert, *text + last_read_idx, size);
+             insert += size;
+          }
+        last_read_idx = read_idx;
+        read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
+     }
+   *insert = 0;
+}
+
+/**
+ * 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 entry object is set to autosave.
+ *
+ * @param obj The entry object
+ * @param file The path to the file to load and save
+ * @param format The file format
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_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);
+}
+
+/**
+ * Gets the file to load and save and the file format
+ *
+ * @param obj The entry object
+ * @param file The path to the file to load and save
+ * @param format The file format
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_file_get(const 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 (file) *file = wd->file;
+   if (format) *format = wd->format;
+}
+
+/**
+ * This function writes any changes made to the file set with
+ * elm_entry_file_set()
+ *
+ * @param obj The entry object
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_file_save(Evas_Object *obj)
+{
+   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;
+     }
+   _save(obj);
+   wd->delay_write = ecore_timer_add(2.0, _delay_write, obj);
+}
+
+/**
+ * This sets the entry object to 'autosave' the loaded text file or not.
+ *
+ * @param obj The entry object
+ * @param autosave Autosave the loaded file or not
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_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;
+}
+
+/**
+ * This gets the entry object's 'autosave' status.
+ *
+ * @param obj The entry object
+ * @return Autosave the loaded file or not
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_autosave_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->autosave;
+}
+
+
+/**
+ * Control pasting of text and images for the widget.
+ *
+ * Normally the entry allows both text and images to be pasted.  By setting
+ * textonly to be true, this prevents images from being pasted.
+ *
+ * Note this only changes the behaviour of text.
+ *
+ * @param obj The entry object
+ * @param pmode paste mode - 0 is text only, 1 is text+image+other.
+ *
+ * @ingroup Entry
+ */
+EAPI void
+elm_entry_cnp_textonly_set(Evas_Object *obj, Eina_Bool textonly)
+{
+   Elm_Sel_Format format = ELM_SEL_FORMAT_MARKUP;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   textonly = !!textonly;
+   if (wd->textonly == textonly) return;
+   wd->textonly = !!textonly;
+   if (!textonly) format |= ELM_SEL_FORMAT_IMAGE;
+   elm_drop_target_add(obj, format, _drag_drop_cb, NULL);
+}
+
+/**
+ * Getting elm_entry text paste/drop mode.
+ *
+ * In textonly mode, only text may be pasted or dropped into the widget.
+ *
+ * @param obj The entry object
+ * @return If the widget only accepts text from pastes.
+ *
+ * @ingroup Entry
+ */
+EAPI Eina_Bool
+elm_entry_cnp_textonly_get(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->textonly;
+}
+
diff --git a/src/lib/elm_flip.c b/src/lib/elm_flip.c
new file mode 100644 (file)
index 0000000..7375984
--- /dev/null
@@ -0,0 +1,700 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Flip Flip
+ *
+ * This holds 2 content objects: one on the front and one on the back. It
+ * allows you to flip from front to back and vice-versa using various effects.
+ *
+ * Supported flip types:
+ * ELM_FLIP_ROTATE_Y_CENTER_AXIS
+ * ELM_FLIP_ROTATE_X_CENTER_AXIS
+ * ELM_FLIP_ROTATE_XZ_CENTER_AXIS
+ * ELM_FLIP_ROTATE_YZ_CENTER_AXIS
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * "animate,done" - when a flip animation is finished
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Ecore_Animator *animator;
+   double start, len;
+   Elm_Flip_Mode mode;
+   Evas_Object *clip;
+   struct {
+      Evas_Object *content, *clip;
+   } front, back;
+   Eina_Bool state : 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 _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 _configure(Evas_Object *obj);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->animator) ecore_animator_del(wd->animator);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _sizing_eval(obj);
+}
+
+static Eina_Bool
+_elm_flip_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd)
+     return EINA_FALSE;
+
+   /* Try Focus cycle in subitem */
+   if (wd->state)
+     return elm_widget_focus_next_get(wd->front.content, dir, next);
+   else
+     return elm_widget_focus_next_get(wd->back.content, dir, next);
+
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1, minw2 = -1, minh2 = -1;
+   Evas_Coord maxw = -1, maxh = -1, maxw2 = -1, maxh2 = -1;
+   if (!wd) return;
+   if (wd->front.content)
+     evas_object_size_hint_min_get(wd->front.content, &minw, &minh);
+   if (wd->back.content)
+     evas_object_size_hint_min_get(wd->back.content, &minw2, &minh2);
+   if (wd->front.content)
+     evas_object_size_hint_max_get(wd->front.content, &maxw, &maxh);
+   if (wd->back.content)
+     evas_object_size_hint_max_get(wd->back.content, &maxw2, &maxh2);
+   
+   if (minw2 > minw) minw = minw2;
+   if (minh2 > minh) minh = minh2;
+   if ((maxw2 >= 0) && (maxw2 < maxw)) maxw = maxw2;
+   if ((maxh2 >= 0) && (maxh2 < maxh)) maxh = maxh2;
+   
+   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;
+   if (sub == wd->front.content)
+     {
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       wd->front.content = NULL;
+        evas_object_hide(wd->front.clip);
+       _sizing_eval(obj);
+     }
+   else if (sub == wd->back.content)
+     {
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       wd->back.content = NULL;
+        evas_object_hide(wd->back.clip);
+       _sizing_eval(obj);
+     }
+}
+
+static void
+flip_show_hide(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (elm_flip_front_get(obj))
+     {
+        if (wd->front.content)
+           evas_object_show(wd->front.clip);
+        else
+           evas_object_hide(wd->front.clip);
+        if (wd->back.content)
+           evas_object_hide(wd->back.clip);
+        else
+           evas_object_hide(wd->back.clip);
+     }
+   else
+     {
+        if (wd->front.content)
+           evas_object_hide(wd->front.clip);
+        else
+           evas_object_hide(wd->front.clip);
+        if (wd->back.content)
+           evas_object_show(wd->back.clip);
+        else
+           evas_object_hide(wd->back.clip);
+     }
+}
+
+static Eina_Bool
+_flip(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double t = ecore_loop_time_get() - wd->start;
+   Evas_Coord x, y, w, h;
+   double p, deg;
+   Evas_Map *mf, *mb;
+   Evas_Coord cx, cy, px, py, foc;
+   int lx, ly, lz, lr, lg, lb, lar, lag, lab;
+   if (!wd->animator) return ECORE_CALLBACK_CANCEL;
+   t = t / wd->len;
+   if (t > 1.0) t = 1.0;
+
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+
+   mf = evas_map_new(4);
+   evas_map_smooth_set(mf, 0);
+   mb = evas_map_new(4);
+   evas_map_smooth_set(mb, 0);
+
+   if (wd->front.content)
+     {
+        evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
+        evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
+     }
+   if (wd->back.content)
+     {
+        evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
+        evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
+     }
+   
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   
+   cx = x + (w / 2);
+   cy = y + (h / 2);
+
+   px = x + (w / 2);
+   py = y + (h / 2);
+   foc = 2048;
+   
+   lx = cx;
+   ly = cy;
+   lz = -10000;
+   lr = 255;
+   lg = 255;
+   lb = 255;
+   lar = 0;
+   lag = 0;
+   lab = 0;
+   
+   switch (wd->mode)
+     {
+     case ELM_FLIP_ROTATE_Y_CENTER_AXIS:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        if (wd->state) deg = 180.0 * p;
+        else deg = 180 + (180.0 * p);
+        evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, 0);
+        evas_map_util_3d_rotate(mb, 0.0, deg + 180.0, 0.0, cx, cy, 0);
+        break;
+     case ELM_FLIP_ROTATE_X_CENTER_AXIS:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        if (wd->state) deg = 180.0 * p;
+        else deg = 180 + (180.0 * p);
+        evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, 0);
+        evas_map_util_3d_rotate(mb, deg + 180.0, 0.0, 0.0, cx, cy, 0);
+        break;
+     case ELM_FLIP_ROTATE_XZ_CENTER_AXIS:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        if (wd->state) deg = 180.0 * p;
+        else deg = 180 + (180.0 * p);
+        evas_map_util_3d_rotate(mf, deg, 0.0, deg, cx, cy, 0);
+        evas_map_util_3d_rotate(mb, deg + 180.0, 0.0, deg + 180.0, cx, cy, 0);
+        break;
+     case ELM_FLIP_ROTATE_YZ_CENTER_AXIS:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        if (wd->state) deg = 180.0 * p;
+        else deg = 180 + (180.0 * p);
+        evas_map_util_3d_rotate(mf, 0.0, deg, deg, cx, cy, 0);
+        evas_map_util_3d_rotate(mb, 0.0, deg + 180.0, deg + 180.0, cx, cy, 0);
+        break;
+     case ELM_FLIP_CUBE_LEFT:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        deg = -90.0 * p;
+        if (wd->state)
+          {
+            evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
+            evas_map_util_3d_rotate(mb, 0.0, deg + 90, 0.0, cx, cy, w / 2);
+          }
+        else
+          {
+            evas_map_util_3d_rotate(mf, 0.0, deg + 90, 0.0, cx, cy, w / 2);
+            evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
+          }
+        break;
+     case ELM_FLIP_CUBE_RIGHT:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        deg = 90.0 * p;
+        if (wd->state)
+          {
+            evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
+            evas_map_util_3d_rotate(mb, 0.0, deg - 90, 0.0, cx, cy, w / 2);
+          }
+        else
+          {
+            evas_map_util_3d_rotate(mf, 0.0, deg - 90, 0.0, cx, cy, w / 2);
+            evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
+          }
+        break;
+     case ELM_FLIP_CUBE_UP:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        deg = -90.0 * p;
+        if (wd->state)
+          {
+            evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
+            evas_map_util_3d_rotate(mb, deg + 90, 0.0, 0.0, cx, cy, h / 2);
+          }
+        else
+          {
+            evas_map_util_3d_rotate(mf, deg + 90, 0.0, 0.0, cx, cy, h / 2);
+            evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
+          }
+        break;
+     case ELM_FLIP_CUBE_DOWN:
+        p = 1.0 - t;
+        p = 1.0 - (p * p);
+        deg = 90.0 * p;
+        if (wd->state)
+          {
+            evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
+            evas_map_util_3d_rotate(mb, deg - 90, 0.0, 0.0, cx, cy, h / 2);
+          }
+        else
+          {
+            evas_map_util_3d_rotate(mf, deg - 90, 0.0, 0.0, cx, cy, h / 2);
+            evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
+          }
+        break;
+     default:
+        break;
+     }
+
+   
+   if (wd->front.content)
+     {
+        evas_map_util_3d_lighting(mf, lx, ly, lz, lr, lg, lb, lar, lag, lab);
+        evas_map_util_3d_perspective(mf, px, py, 0, foc);
+        evas_object_map_set(wd->front.content, mf);
+        evas_object_map_enable_set(wd->front.content, 1);
+        if (evas_map_util_clockwise_get(mf)) evas_object_show(wd->front.clip);
+        else evas_object_hide(wd->front.clip);
+     }
+      
+   if (wd->back.content)
+     {
+        evas_map_util_3d_lighting(mb, lx, ly, lz, lr, lg, lb, lar, lag, lab);
+        evas_map_util_3d_perspective(mb, px, py, 0, foc);
+        evas_object_map_set(wd->back.content, mb);
+        evas_object_map_enable_set(wd->back.content, 1);
+        if (evas_map_util_clockwise_get(mb)) evas_object_show(wd->back.clip);
+        else evas_object_hide(wd->back.clip);
+     }
+   
+   evas_map_free(mf);
+   evas_map_free(mb);
+   
+   if (t >= 1.0)
+     {
+        evas_object_map_enable_set(wd->front.content, 0);
+        evas_object_map_enable_set(wd->back.content, 0);
+        // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
+        evas_object_resize(wd->front.content, 0, 0);
+        evas_object_resize(wd->back.content, 0, 0);
+        evas_smart_objects_calculate(evas_object_evas_get(obj));
+        // FIXME: end hack
+        wd->animator = NULL;
+        wd->state = !wd->state;
+        _configure(obj);
+        evas_object_smart_callback_call(obj, "animate,done", NULL);
+        return ECORE_CALLBACK_CANCEL;
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_configure(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord x, y, w, h;
+   if (!wd) return;
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   if (wd->front.content)
+     {
+        if (!wd->animator)
+          evas_object_move(wd->front.content, x, y);
+        evas_object_resize(wd->front.content, w, h);
+     }
+   if (wd->back.content)
+     {
+        if (!wd->animator)
+          evas_object_move(wd->back.content, x, y);
+        evas_object_resize(wd->back.content, w, h);
+     }
+   _flip(obj);
+}
+
+static void
+_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   _configure(obj);
+}
+
+static void
+_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{    
+   _configure(obj);
+}
+
+static Eina_Bool
+_animate(void *data)
+{
+   return _flip(data);
+}
+
+/**
+ * Add a new flip to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Flip
+ */
+EAPI Evas_Object *
+elm_flip_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "flip");
+   elm_widget_type_set(obj, "flip");
+   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_focus_next_hook_set(obj, _elm_flip_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->clip = evas_object_rectangle_add(e);
+   evas_object_static_clip_set(wd->clip, 1);
+   evas_object_color_set(wd->clip, 255, 255, 255, 255);
+   evas_object_move(wd->clip, -49999, -49999);
+   evas_object_resize(wd->clip, 99999, 99999);
+   elm_widget_sub_object_add(obj, wd->clip);
+   evas_object_clip_set(wd->clip, evas_object_clip_get(obj));
+   evas_object_smart_member_add(wd->clip, obj);
+   
+   wd->front.clip = evas_object_rectangle_add(e);
+   evas_object_static_clip_set(wd->front.clip, 1);
+   evas_object_data_set(wd->front.clip, "_elm_leaveme", obj);
+   evas_object_color_set(wd->front.clip, 255, 255, 255, 255);
+   evas_object_move(wd->front.clip, -49999, -49999);
+   evas_object_resize(wd->front.clip, 99999, 99999);
+   elm_widget_sub_object_add(obj, wd->front.clip);
+   evas_object_smart_member_add(wd->front.clip, obj);
+   evas_object_clip_set(wd->front.clip, wd->clip);
+   
+   wd->back.clip = evas_object_rectangle_add(e);
+   evas_object_static_clip_set(wd->back.clip, 1);
+   evas_object_data_set(wd->back.clip, "_elm_leaveme", obj);
+   evas_object_color_set(wd->back.clip, 255, 255, 255, 255);
+   evas_object_move(wd->back.clip, -49999, -49999);
+   evas_object_resize(wd->back.clip, 99999, 99999);
+   elm_widget_sub_object_add(wd->back.clip, obj);
+   evas_object_smart_member_add(obj, wd->back.clip);
+   evas_object_clip_set(wd->back.clip, wd->clip);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);
+   
+   wd->state = 1;
+     
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the front content of the flip widget.
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_flip_content_front_unset() function.
+ *
+ * @param obj The flip object
+ * @param content The new front content object
+ *
+ * @ingroup Flip
+ */
+EAPI void
+elm_flip_content_front_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->front.content == content) return;
+   if (wd->front.content) evas_object_del(wd->back.content);
+   wd->front.content = content;
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+        evas_object_smart_member_add(content, obj);
+        evas_object_clip_set(content, wd->front.clip);
+       evas_object_event_callback_add(content,
+                                       EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       _sizing_eval(obj);
+     }
+   // force calc to contents are the right size before transition
+   evas_smart_objects_calculate(evas_object_evas_get(obj));
+   flip_show_hide(obj);
+   _configure(obj);
+}
+
+/**
+ * Set the back content of the flip widget.
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_flip_content_back_unset() function.
+ *
+ * @param obj The flip object
+ * @param content The new back content object
+ *
+ * @ingroup Flip
+ */
+EAPI void
+elm_flip_content_back_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->back.content == content) return;
+   if (wd->back.content) evas_object_del(wd->back.content);
+   wd->back.content = content;
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+        evas_object_smart_member_add(content, obj);
+        evas_object_clip_set(content, wd->back.clip);
+       evas_object_event_callback_add(content,
+                                       EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       _sizing_eval(obj);
+     }
+   // force calc to contents are the right size before transition
+   evas_smart_objects_calculate(evas_object_evas_get(obj));
+   flip_show_hide(obj);
+   _configure(obj);
+}
+
+/**
+ * Get the front content used for the flip
+ *
+ * Return the front content object which is set for this widget.
+ *
+ * @param obj The flip object
+ * @return The front content object that is being used
+ *
+ * @ingroup Flip
+ */
+EAPI Evas_Object *
+elm_flip_content_front_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return wd->front.content;
+}
+
+
+/**
+ * Get the back content used for the flip
+ *
+ * Return the back content object which is set for this widget.
+ *
+ * @param obj The flip object
+ * @return The back content object that is being used
+ *
+ * @ingroup Flip
+ */
+EAPI Evas_Object *
+elm_flip_content_back_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return wd->back.content;
+}
+
+/**
+ * Unset the front content used for the flip
+ *
+ * Unparent and return the front content object which was set for this widget.
+ *
+ * @param obj The flip object
+ * @return The front content object that was being used
+ *
+ * @ingroup Flip
+ */
+EAPI Evas_Object *
+elm_flip_content_front_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->front.content) return NULL;
+   Evas_Object *content = wd->front.content;
+   evas_object_clip_unset(content);
+   elm_widget_sub_object_del(obj, content);
+   evas_object_smart_member_del(content);
+   wd->front.content = NULL;
+   return content;
+}
+
+/**
+ * Unset the back content used for the flip
+ *
+ * Unparent and return the back content object which was set for this widget.
+ *
+ * @param obj The flip object
+ * @return The back content object that was being used
+ *
+ * @ingroup Flip
+ */
+EAPI Evas_Object *
+elm_flip_content_back_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->back.content) return NULL;
+   Evas_Object *content = wd->back.content;
+   evas_object_clip_unset(content);
+   elm_widget_sub_object_del(obj, content);
+   evas_object_smart_member_del(content);
+   wd->back.content = NULL;
+   return content;
+}
+
+/**
+ * Get flip front visibility state
+ *
+ * @param obj The flip object
+ * @return If front front is showing or not currently
+ *
+ * @ingroup Flip
+ */
+EAPI Eina_Bool
+elm_flip_front_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->state;
+}
+
+/**
+ * Set flip perspective
+ *
+ * @param obj The flip object
+ * @param foc The coordinate to set the focus on
+ * @param x The X coordinate
+ * @param y The Y coordinate
+ *
+ * NOTE: This function currently does nothing.
+ *
+ * @ingroup Flip
+ */
+EAPI void
+elm_flip_perspective_set(Evas_Object *obj, Evas_Coord foc __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+}
+
+/**
+ * Runs the flip animation
+ *
+ * @param obj The flip object
+ * @param mode The mode type.  Currently accepted modes are:
+ *
+ * ELM_FLIP_ROTATE_Y_CENTER_AXIS
+ * ELM_FLIP_ROTATE_X_CENTER_AXIS
+ * ELM_FLIP_ROTATE_XZ_CENTER_AXIS
+ * ELM_FLIP_ROTATE_YZ_CENTER_AXIS
+ * ELM_FLIP_CUBE_LEFT
+ * ELM_FLIP_CUBE_RIGHT
+ * 
+ * FIXME: add - ELM_FLIP_CUBE_UP
+ * FIXMEL add - ELM_FLIP_CUBE_DOWN
+ *
+ * @ingroup Flip
+ */
+EAPI void
+elm_flip_go(Evas_Object *obj, Elm_Flip_Mode mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (!wd->animator) wd->animator = ecore_animator_add(_animate, obj);
+   flip_show_hide(obj);
+   wd->mode = mode;
+   wd->start = ecore_loop_time_get();
+   wd->len = 0.5;
+   // force calc to contents are the right size before transition
+   evas_smart_objects_calculate(evas_object_evas_get(obj));
+   _flip(obj);
+   // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
+   evas_object_map_enable_set(wd->front.content, 0);
+   evas_object_map_enable_set(wd->back.content, 0);
+   evas_object_resize(wd->front.content, 0, 0);
+   evas_object_resize(wd->back.content, 0, 0);
+   evas_smart_objects_calculate(evas_object_evas_get(obj));
+   _configure(obj);
+   // FIXME: end hack
+}
diff --git a/src/lib/elm_flipselector.c b/src/lib/elm_flipselector.c
new file mode 100644 (file)
index 0000000..3b783e8
--- /dev/null
@@ -0,0 +1,1158 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @addtogroup Flipselector Flipselector
+ *
+ * A flip selector is a widget to show a set of label items, one at a
+ * time, with an animation when one changes the current selection
+ * (like the flip of calendar sheets, in the default theme).
+ */
+
+/* TODO: ideally, the default theme would use map{} blocks on the TEXT
+   parts to implement their fading in/out propertly (as in the clock
+   widget) */
+/* TODO: if one ever wants to extend it to receiving generic widgets
+   as items, be my guest. in this case, remember to implement the
+   items tooltip infra. */
+/* TODO: implement disabled mode -- disable_hook() and stuff. */
+/* TODO: fix default theme image borders for looong strings as item
+   labels. */
+/* TODO: set text elipsis on labels if one enforces mininum size on
+ * the overall widget less the required for displaying it. */
+/* TODO: find a way to, in the default theme, to detect we are
+ * bootstrapping (receiving the 1st message) and populate the downmost
+ * TEXT parts with the same text as the upmost, where appropriate. */
+
+#define FLIP_FIRST_INTERVAL (0.85)
+#define FLIP_MIN_INTERVAL (0.1)
+#define MSG_FLIP_DOWN (1)
+#define MSG_FLIP_UP (2)
+#define MAX_LEN_DEFAULT (50)
+
+#define DATA_GET eina_list_data_get
+
+struct _Elm_Flipselector_Item {
+   Elm_Widget_Item base;
+   const char *label;
+   Evas_Smart_Cb func;
+   void *data;
+   int deleted : 1;
+};
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data {
+   Evas_Object *self;
+   Evas_Object *base;
+   Eina_List *items;
+   Eina_List *current;
+   Eina_List *sentinel; /* item containing the largest label string */
+   int walking;
+   unsigned int max_len;
+   Ecore_Timer *spin;
+   double interval, first_interval;
+};
+
+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 _update_view(Evas_Object *obj);
+static void _callbacks_set(Evas_Object *obj);
+static void _flip_up(Widget_Data *wd);
+static void _flip_down(Widget_Data *wd);
+
+static const char SIG_SELECTED[] = "selected";
+static const char SIG_UNDERFLOWED[] = "underflowed";
+static const char SIG_OVERFLOWED[] = "overflowed";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_SELECTED, ""},
+  {SIG_UNDERFLOWED, ""},
+  {SIG_OVERFLOWED, ""},
+  {NULL, NULL}
+};
+
+#define ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(it, ...)               \
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, __VA_ARGS__);            \
+  if (it->deleted)                                                     \
+    {                                                                  \
+       ERR(""#it" has been DELETED.\n");                               \
+       return __VA_ARGS__;                                             \
+    }                                                                  \
+
+static Elm_Flipselector_Item *
+_item_new(Evas_Object *obj, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   unsigned int len;
+   Elm_Flipselector_Item *it;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   it = elm_widget_item_new(obj, Elm_Flipselector_Item);
+   if (!it)
+     return NULL;
+
+   len = strlen(label);
+   if (len > wd->max_len)
+     len = wd->max_len;
+
+   it->label = eina_stringshare_add_length(label, len);
+   it->func = func;
+   it->base.data = data;
+
+   /* TODO: no view here, but if one desires general contents in the
+    * future... */
+   return it;
+}
+
+static inline void
+_item_free(Elm_Flipselector_Item *it)
+{
+   eina_stringshare_del(it->label);
+   elm_widget_item_del(it);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Elm_Flipselector_Item *item;
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (wd->walking)
+     ERR("flipselector deleted while walking.\n");
+
+   EINA_LIST_FREE(wd->items, item)
+     _item_free(item);
+
+   if (wd->spin) ecore_timer_del(wd->spin);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   const char *max_len;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   _elm_theme_object_set(obj, wd->base, "flipselector", "base",
+                        elm_widget_style_get(obj));
+   edje_object_scale_set(wd->base,
+                        elm_widget_scale_get(obj) * _elm_config->scale);
+
+   max_len = edje_object_data_get(wd->base, "max_len");
+   if (!max_len)
+     wd->max_len = MAX_LEN_DEFAULT;
+   else
+     {
+       wd->max_len = atoi(max_len);
+       if (!wd->max_len)
+         wd->max_len = MAX_LEN_DEFAULT;
+     }
+
+   _update_view(obj);
+   _sizing_eval(obj);
+}
+
+static void
+_sentinel_eval(Widget_Data *wd)
+{
+   Elm_Flipselector_Item *it;
+   Eina_List *l;
+
+   if (!wd->items)
+     {
+       wd->sentinel = NULL;
+       return;
+     }
+
+   wd->sentinel = wd->items;
+
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+       if (strlen(elm_flipselector_item_label_get(it)) >
+           strlen(elm_flipselector_item_label_get(DATA_GET(wd->sentinel))))
+         wd->sentinel = l;
+     }
+}
+
+/* TODO: create a flag to avoid looping here all times */
+static void
+_flipselector_process_deletions(Widget_Data *wd)
+{
+   Elm_Flipselector_Item *it;
+   Eina_List *l;
+   Eina_Bool skip = EINA_TRUE;
+   Eina_Bool sentinel_eval = EINA_FALSE;
+
+   wd->walking++; /* avoid nested deletions */
+
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+       if (!it->deleted)
+         continue;
+
+       if (wd->current == l)
+         {
+            if (wd->current == wd->sentinel)
+              sentinel_eval = EINA_TRUE;
+
+            wd->current = eina_list_prev(wd->current);
+         }
+       wd->items = eina_list_remove(wd->items, it);
+
+       if (!wd->current)
+         wd->current = wd->items;
+
+        _item_free(it);
+       skip = EINA_FALSE;
+
+       if (eina_list_count(wd->items) <= 1)
+         edje_object_signal_emit(wd->base, "elm,state,button,hidden", "elm");
+       else
+         edje_object_signal_emit(wd->base, "elm,state,button,visible", "elm");
+     }
+
+   if (!skip)
+     _update_view(wd->self);
+
+   if (sentinel_eval)
+     _sentinel_eval(wd);
+
+   wd->walking--;
+}
+
+static inline void
+_flipselector_walk(Widget_Data *wd)
+{
+   if (wd->walking < 0)
+     {
+       ERR("walking was negative. fixed!\n");
+       wd->walking = 0;
+     }
+   wd->walking++;
+}
+
+static inline void
+_flipselector_unwalk(Widget_Data *wd)
+{
+   wd->walking--;
+   if (wd->walking < 0)
+     {
+       ERR("walking became negative. fixed!\n");
+       wd->walking = 0;
+     }
+
+   if (wd->walking)
+     return;
+
+   _flipselector_process_deletions(wd);
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   Evas_Event_Key_Down *ev;
+   Widget_Data *wd;
+   Eina_Bool is_up = EINA_TRUE;
+
+   if (type != EVAS_CALLBACK_KEY_DOWN)
+     return EINA_FALSE;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return EINA_FALSE;
+
+   ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     return EINA_FALSE;
+
+   if (elm_widget_disabled_get(obj))
+     return EINA_FALSE;
+
+   if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
+     is_up = EINA_FALSE;
+   else if ((strcmp(ev->keyname, "Up")) && (strcmp(ev->keyname, "KP_Up")))
+     return EINA_FALSE;
+
+   if (wd->spin) ecore_timer_del(wd->spin);
+
+   /* TODO: if direction setting via API is not coming in, replace
+      these calls by flip_{next,prev} */
+   _flipselector_walk(wd);
+   if (is_up)
+     _flip_up(wd);
+   else
+     _flip_down(wd);
+   _flipselector_unwalk(wd);
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+}
+
+static void
+_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   /* FIXME: no treatment of this signal so far */
+   if (elm_widget_focus_get(obj))
+     {
+       edje_object_signal_emit(wd->base, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->base, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->base, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->base, EINA_FALSE);
+     }
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   const char *tmp = NULL;
+   Evas_Coord minw = -1, minh = -1, w, h;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   elm_coords_finger_size_adjust(1, &minw, 2, &minh);
+
+   if (wd->sentinel)
+     {
+       const char *label = \
+         elm_flipselector_item_label_get(DATA_GET(wd->sentinel));
+
+       tmp = edje_object_part_text_get(wd->base, "top");
+       edje_object_part_text_set(wd->base, "top", label);
+     }
+
+   edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
+   elm_coords_finger_size_adjust(1, &minw, 2, &minh);
+   evas_object_size_hint_min_get(obj, &w, &h);
+
+   if (wd->sentinel)
+     edje_object_part_text_set(wd->base, "top", tmp);
+
+   if (w > minw) minw = w;
+   if (h > minh) minh = h;
+
+   evas_object_size_hint_min_set(obj, minw, minh);
+}
+
+static void
+_update_view(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   const char *label;
+   Elm_Flipselector_Item *item;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   label = NULL;
+   item = DATA_GET(wd->current);
+   if (item)
+     label = item->label;
+
+   edje_object_part_text_set(wd->base, "top", label ? label : "");
+   edje_object_part_text_set(wd->base, "bottom", label ? label : "");
+
+   edje_object_message_signal_process(wd->base);
+}
+
+static void
+_changed(Widget_Data *wd)
+{
+   Elm_Flipselector_Item *item;
+
+   item = DATA_GET(wd->current);
+   if (!item)
+     return;
+
+   if (item->func)
+     item->func((void *)item->base.data, item->base.widget, item);
+   if (!item->deleted)
+     evas_object_smart_callback_call(wd->self, SIG_SELECTED, item);
+}
+
+static void
+_send_msg(Widget_Data *wd, int flipside, char *label)
+{
+   Edje_Message_String msg;
+
+   msg.str = label;
+   edje_object_message_send(wd->base, EDJE_MESSAGE_STRING, flipside, &msg);
+   edje_object_message_signal_process(wd->base);
+
+   _changed(wd);
+}
+
+static void
+_flip_up(Widget_Data *wd)
+{
+   Elm_Flipselector_Item *item;
+
+   if (!wd->current)
+     return;
+
+   if (wd->current == wd->items)
+     {
+       wd->current = eina_list_last(wd->items);
+       evas_object_smart_callback_call(wd->self, SIG_UNDERFLOWED, NULL);
+     }
+   else
+     wd->current = eina_list_prev(wd->current);
+
+   item = DATA_GET(wd->current);
+   if (!item)
+     return;
+
+   _send_msg(wd, MSG_FLIP_UP, (char *)item->label);
+}
+
+static Eina_Bool
+_signal_val_up(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd)
+     goto val_up_exit_on_error;
+
+   _flipselector_walk(wd);
+
+   if (wd->interval > FLIP_MIN_INTERVAL)
+     wd->interval = wd->interval / 1.05;
+
+   ecore_timer_interval_set(wd->spin, wd->interval);
+
+   _flip_up(wd);
+
+   _flipselector_unwalk(wd);
+
+   return ECORE_CALLBACK_RENEW;
+
+ val_up_exit_on_error:
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_signal_val_up_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd)
+     return;
+
+   wd->interval = wd->first_interval;
+
+   if (wd->spin)
+     ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _signal_val_up, data);
+
+   _signal_val_up(data);
+}
+
+static void
+_flip_down(Widget_Data *wd)
+{
+   Elm_Flipselector_Item *item;
+
+   if (!wd->current)
+     return;
+
+   wd->current = eina_list_next(wd->current);
+   if (!wd->current)
+     {
+       wd->current = wd->items;
+       evas_object_smart_callback_call(wd->self, SIG_OVERFLOWED, NULL);
+     }
+
+   item = DATA_GET(wd->current);
+   if (!item)
+     return;
+
+   _send_msg(wd, MSG_FLIP_DOWN, (char *)item->label);
+}
+
+static Eina_Bool
+_signal_val_down(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd)
+     goto val_down_exit_on_error;
+
+   _flipselector_walk(wd);
+
+   if (wd->interval > FLIP_MIN_INTERVAL)
+     wd->interval = wd->interval / 1.05;
+   ecore_timer_interval_set(wd->spin, wd->interval);
+
+   _flip_down(wd);
+
+   _flipselector_unwalk(wd);
+
+   return ECORE_CALLBACK_RENEW;
+
+ val_down_exit_on_error:
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_signal_val_down_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd)
+     return;
+
+   wd->interval = wd->first_interval;
+
+   if (wd->spin)
+     ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _signal_val_down, data);
+
+   _signal_val_down(data);
+}
+
+static void
+_signal_val_change_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd)
+     return;
+
+   if (wd->spin)
+     ecore_timer_del(wd->spin);
+   wd->spin = NULL;
+}
+
+static void
+_callbacks_set(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   edje_object_signal_callback_add(wd->base, "elm,action,up,start",
+                                  "", _signal_val_up_start, obj);
+   edje_object_signal_callback_add(wd->base, "elm,action,up,stop",
+                                  "", _signal_val_change_stop, obj);
+   edje_object_signal_callback_add(wd->base, "elm,action,down,start",
+                                  "", _signal_val_down_start, obj);
+   edje_object_signal_callback_add(wd->base, "elm,action,down,stop",
+                                  "", _signal_val_change_stop, obj);
+}
+
+/**
+ * Add a new flipselector to the parent.
+ *
+ * @param parent The parent object
+ * @return The new object or NULL, if it cannot be created
+ *
+ * @ingroup Flipselector
+ */
+EAPI Evas_Object *
+elm_flipselector_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   wd->self = obj;
+   ELM_SET_WIDTYPE(widtype, "flipselector");
+   elm_widget_type_set(obj, "flipselector");
+   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);
+   /* TODO: elm_widget_disable_hook_set(obj, _disable_hook); */
+
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->base = edje_object_add(e);
+   elm_widget_resize_object_set(obj, wd->base);
+
+   _callbacks_set(obj);
+
+   wd->first_interval = FLIP_FIRST_INTERVAL;
+
+   _theme_hook(obj);
+
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Select next item of a flipselector.
+ *
+ * @param obj The flipselector object
+ *
+ * @ingroup Flipselector
+ */
+EAPI void
+elm_flipselector_flip_next(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (wd->spin) ecore_timer_del(wd->spin);
+
+   _flipselector_walk(wd);
+   _flip_down(wd);
+   _flipselector_unwalk(wd);
+}
+
+/**
+ * Select previous item of a flipselector.
+ *
+ * @param obj The flipselector object
+ *
+ * @ingroup Flipselector
+ */
+EAPI void
+elm_flipselector_flip_prev(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (wd->spin) ecore_timer_del(wd->spin);
+
+   _flipselector_walk(wd);
+   _flip_up(wd);
+   _flipselector_unwalk(wd);
+}
+
+/**
+ * Append item to a flipselector.
+ *
+ * @param obj The flipselector object
+ * @param label The label of new item
+ * @param func Convenience function called when item selected
+ * @param data Data passed to @p func above
+ * @return A handle to the item added or NULL, on errors
+ *
+ * @note The maximum length of the label is going to be determined by
+ * the widget's theme. Strings larger than that value are going to be
+ * truncated.
+ *
+ * @ingroup Flipselector
+ */
+EAPI Elm_Flipselector_Item *
+elm_flipselector_item_append(Evas_Object *obj, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Elm_Flipselector_Item *item;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return NULL;
+
+   item = _item_new(obj, label, func, data);
+   if (!item)
+     return NULL;
+
+   wd->items = eina_list_append(wd->items, item);
+   if (!wd->current) {
+      wd->current = wd->items;
+      _update_view(obj);
+   }
+
+   if (!wd->sentinel ||
+       (strlen(elm_flipselector_item_label_get(item)) >
+       strlen(elm_flipselector_item_label_get(DATA_GET(wd->sentinel)))))
+     {
+       wd->sentinel = eina_list_last(wd->items);
+       _sizing_eval(obj);
+     }
+
+   if (eina_list_count(wd->items) >= 2)
+     edje_object_signal_emit(wd->base, "elm,state,button,visible", "elm");
+
+   return item;
+}
+
+/**
+ * Prepend item to a flipselector.
+ *
+ * @param obj The flipselector object
+ * @param label The label of new item
+ * @param func Convenience function called when item selected
+ * @param data Data passed to @p func above
+ * @return A handle to the item added or NULL, on errors
+ *
+ * @note The maximum length of the label is going to be determined by
+ * the widget's theme. Strings larger than that value are going to be
+ * truncated.
+ *
+ * @ingroup Flipselector
+ */
+EAPI Elm_Flipselector_Item *
+elm_flipselector_item_prepend(Evas_Object *obj, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Elm_Flipselector_Item *item;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return NULL;
+
+   item = _item_new(obj, label, func, data);
+   if (!item)
+     return NULL;
+
+   wd->items = eina_list_prepend(wd->items, item);
+   if (!wd->current) {
+      wd->current = wd->items;
+      _update_view(obj);
+   }
+
+   if (!wd->sentinel ||
+       (strlen(elm_flipselector_item_label_get(item)) >
+       strlen(elm_flipselector_item_label_get(DATA_GET(wd->sentinel)))))
+     {
+       wd->sentinel = wd->items;
+       _sizing_eval(obj);
+     }
+
+   if (eina_list_count(wd->items) >= 2)
+     edje_object_signal_emit(wd->base, "elm,state,button,visible", "elm");
+
+   return item;
+}
+
+/* TODO: account for deleted items?  */
+/**
+ * Get a list of items in the flipselector.
+ *
+ * @param obj The flipselector object
+ * @return The list of items, or NULL on errors.
+ *
+ * @ingroup Flipselector
+ */
+EAPI const Eina_List *
+elm_flipselector_items_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->items;
+}
+
+/**
+ * Get the first item in the flipselector
+ *
+ * @param obj The flipselector object
+ * @return The first item, or NULL if none
+ *
+ * @ingroup Flipselector
+ */
+EAPI Elm_Flipselector_Item *
+elm_flipselector_first_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Elm_Flipselector_Item *it;
+   Widget_Data *wd;
+   Eina_List *l;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd || !wd->items)
+     return NULL;
+
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+       if (it->deleted)
+         continue;
+
+       return it;
+     }
+
+   return NULL;
+}
+
+/**
+ * Get the last item in the flipselector
+ *
+ * @param obj The flipselector object
+ * @return The last item, or NULL if none
+ *
+ * @ingroup Flipselector
+ */
+EAPI Elm_Flipselector_Item *
+elm_flipselector_last_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Elm_Flipselector_Item *it;
+   Widget_Data *wd;
+   Eina_List *l;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd || !wd->items)
+     return NULL;
+
+   EINA_LIST_REVERSE_FOREACH(wd->items, l, it)
+     {
+       if (it->deleted)
+         continue;
+
+       return it;
+     }
+
+   return NULL;
+}
+
+/**
+ * Get the selected item in a flipselector.
+ *
+ * @param obj The flipselector object
+ * @return The selected item, or NULL if none
+ *
+ * @ingroup Flipselector
+ */
+EAPI Elm_Flipselector_Item *
+elm_flipselector_selected_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd || !wd->current)
+     return NULL;
+
+   return DATA_GET(wd->current);
+}
+
+/**
+ * Set the selected state of an item
+ *
+ * This sets the selected state (EINA_TRUE selected, EINA_FALSE not selected)
+ * of the given item @p item.
+ * If a new item is selected the previosly selected will be unselected.
+ * If the item @p item is unselected, the first item will be selected.
+ *
+ * @param item The item
+ * @param selected The selected state
+ *
+ * @ingroup Flipselector
+ */
+EAPI void
+elm_flipselector_item_selected_set(Elm_Flipselector_Item *item, Eina_Bool selected)
+{
+   ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(item);
+
+   Elm_Flipselector_Item *_item, *cur;
+   int flipside = MSG_FLIP_UP;
+   Widget_Data *wd;
+   Eina_List *l;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+     return;
+
+   cur = DATA_GET(wd->current);
+   if ((selected) && (cur == item))
+     return;
+
+   _flipselector_walk(wd);
+
+   if ((!selected) && (cur == item))
+     {
+        EINA_LIST_FOREACH(wd->items, l, _item)
+          {
+             if (!_item->deleted)
+               {
+                  wd->current = l;
+                  _send_msg(wd, MSG_FLIP_UP, (char *)_item->label);
+                  break;
+               }
+          }
+        _flipselector_unwalk(wd);
+        return;
+     }
+
+   EINA_LIST_FOREACH(wd->items, l, _item)
+     {
+       if (_item == cur)
+          flipside = MSG_FLIP_DOWN;
+
+       if (_item == item)
+         {
+            wd->current = l;
+             _send_msg(wd, flipside, (char *)item->label);
+            break;
+         }
+     }
+
+   _flipselector_unwalk(wd);
+}
+
+/*
+ * Get the selected state of @p item.
+ *
+ * @param item The flipselector item
+ * @return If true, the item is selected
+ *
+ * @ingroup Flipselector
+ */
+EAPI Eina_Bool
+elm_flipselector_item_selected_get(const Elm_Flipselector_Item *item)
+{
+   ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return EINA_FALSE;
+   return (eina_list_data_get(wd->current) == item);
+}
+
+/**
+ * Delete a given item from a flipselector.
+ *
+ * @param item The item
+ *
+ * @ingroup Flipselector
+ */
+EAPI void
+elm_flipselector_item_del(Elm_Flipselector_Item *item)
+{
+   ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(item);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+     return;
+
+   if (wd->walking > 0)
+     {
+       item->deleted = EINA_TRUE;
+       return;
+     }
+
+   _flipselector_walk(wd);
+
+   wd->items = eina_list_remove(wd->items, item);
+   _item_free(item);
+   _sentinel_eval(wd);
+
+   _flipselector_unwalk(wd);
+}
+
+/**
+ * Get the label of a given flipselector item.
+ *
+ * @param item The item
+ * @return The label of a given item, or NULL if none
+ *
+ * @ingroup Flipselector
+ */
+EAPI const char *
+elm_flipselector_item_label_get(const Elm_Flipselector_Item *item)
+{
+   ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(item, NULL);
+
+   Elm_Flipselector_Item *_item;
+   Widget_Data *wd;
+   Eina_List *l;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if ((!wd) || (!wd->items))
+     return NULL;
+
+   EINA_LIST_FOREACH(wd->items, l, _item)
+     if (_item == item)
+       return item->label;
+
+   return NULL;
+}
+
+/**
+ * Set the label of a given flipselector item.
+ *
+ * @param item The item
+ * @param label The text label string in UTF-8
+ *
+ * @ingroup Flipselector
+ */
+EAPI void
+elm_flipselector_item_label_set(Elm_Flipselector_Item *item, const char *label)
+{
+   ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(item);
+
+   Widget_Data *wd;
+   Eina_List *l;
+
+   if ((!item) || (!label))
+     return;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if ((!wd) || (!wd->items))
+     return;
+
+   l = eina_list_data_find_list(wd->items, item);
+   if (!l)
+     return;
+
+   eina_stringshare_del(item->label);
+   item->label = eina_stringshare_add_length(label, wd->max_len);
+
+   if (strlen(label) >
+       strlen(elm_flipselector_item_label_get(DATA_GET(wd->sentinel))))
+     wd->sentinel = l;
+
+   if (wd->current == l)
+     {
+       _update_view(item->base.widget);
+       _sizing_eval(wd->self);
+     }
+
+   return;
+}
+
+/**
+ * Gets the item before @p item in a flipselector.
+ *
+ * @param item The item
+ * @return The item before the item @p item
+ *
+ * @ingroup Flipselector
+ */
+EAPI Elm_Flipselector_Item *
+elm_flipselector_item_prev_get(Elm_Flipselector_Item *item)
+{
+   ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(item, NULL);
+
+   Elm_Flipselector_Item *_item;
+   Widget_Data *wd;
+   Eina_List *l;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if ((!wd) || (!wd->items))
+     return NULL;
+
+   EINA_LIST_FOREACH(wd->items, l, _item)
+     if (_item == item)
+       {
+         l = eina_list_prev(l);
+         if (!l)
+           return NULL;
+         return DATA_GET(l);
+       }
+
+   return NULL;
+}
+
+/**
+ * Gets the item after @p item in a flipselector.
+ *
+ * @param item The item
+ * @return The item after the item @p item
+ *
+ * @ingroup Flipselector
+ */
+EAPI Elm_Flipselector_Item *
+elm_flipselector_item_next_get(Elm_Flipselector_Item *item)
+{
+   ELM_FLIPSELECTOR_ITEM_CHECK_DELETED_RETURN(item, NULL);
+
+   Elm_Flipselector_Item *_item;
+   Widget_Data *wd;
+   Eina_List *l;
+
+   wd = elm_widget_data_get(item->base.widget);
+   if ((!wd) || (!wd->items))
+     return NULL;
+
+   EINA_LIST_FOREACH(wd->items, l, _item)
+     if (_item == item)
+       {
+         l = eina_list_next(l);
+         if (!l)
+           return NULL;
+         return DATA_GET(l);
+       }
+
+   return NULL;
+}
+
+/**
+ * Set the flipping interval for the flipselector.
+ *
+ * @param obj The flipselector object
+ * @param interval The interval value in seconds
+ *
+ * The interval value is decreased while the user flips the widget up
+ * or down repeatedly. The next interval value is the previous
+ * interval / 1.05, so it speeds up a bit. Default value is 0.85
+ * seconds.
+ *
+ * @ingroup Flipselector
+ */
+EAPI void
+elm_flipselector_interval_set(Evas_Object *obj, double interval)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   wd->first_interval = interval;
+}
+
+/**
+ * Get the flipping interval of the flipselector.
+ *
+ * @param obj The flipselector object
+ * @return The value of the first interval in seconds
+ *
+ * The interval value is decreased while the user flips the widget up
+ * or down repeatedly. The next interval value is the previous
+ * interval / 1.05, so it speeds up a bit. Default value is 0.85
+ * seconds.
+ *
+ * @ingroup Flipselector
+ */
+EAPI double
+elm_flipselector_interval_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd)
+     return 0.0;
+   return wd->first_interval;
+}
diff --git a/src/lib/elm_font.c b/src/lib/elm_font.c
new file mode 100644 (file)
index 0000000..844fc7b
--- /dev/null
@@ -0,0 +1,128 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+Elm_Font_Properties *
+_elm_font_properties_get(Eina_Hash **font_hash,
+                         const char *font)
+{
+   Elm_Font_Properties *efp = NULL;
+   char *s1;
+
+   s1 = strchr(font, ':');
+   if (s1)
+     {
+        char *s2, *name, *style;
+        int len;
+
+        len = s1 - font;
+        name = calloc(sizeof(char), len + 1);
+        strncpy(name, font, len);
+
+        /* get subname (should be english)  */
+        s2 = strchr(name, ',');
+        if (s2)
+          {
+             len = s2 - name;
+             name = realloc(name, sizeof(char) * len + 1);
+             memset(name, 0, sizeof(char) * len + 1);
+             strncpy(name, font, len);
+          }
+
+        if (!strncmp(s1, ELM_FONT_TOKEN_STYLE, strlen(ELM_FONT_TOKEN_STYLE)))
+          {
+             style = s1 + strlen(ELM_FONT_TOKEN_STYLE);
+
+             if (font_hash) efp = eina_hash_find(*font_hash, name);
+             if (!efp)
+               {
+                  efp = calloc(1, sizeof(Elm_Font_Properties));
+                  efp->name = eina_stringshare_add(name);
+                  if (font_hash)
+                    {
+                       if (!*font_hash)
+                         *font_hash = eina_hash_string_superfast_new(NULL);
+                       eina_hash_add(*font_hash, name, efp);
+                    }
+               }
+             s2 = strchr(style, ',');
+             if (s2)
+               {
+                  char *style_old;
+
+                  len = s2 - style;
+                  style_old = style;
+                  style = calloc(sizeof(char), len + 1);
+                  strncpy(style, style_old, len);
+                  efp->styles = eina_list_append(efp->styles,
+                                                 eina_stringshare_add(style));
+                  free(style);
+               }
+             else
+               efp->styles = eina_list_append(efp->styles,
+                                              eina_stringshare_add(style));
+          }
+        free(name);
+     }
+   else
+     {
+        if (font_hash) efp = eina_hash_find(*font_hash, font);
+        if (!efp)
+          {
+             efp = calloc(1, sizeof(Elm_Font_Properties));
+             efp->name = eina_stringshare_add(font);
+             if (font_hash)
+               {
+                  if (!*font_hash)
+                    *font_hash = eina_hash_string_superfast_new(NULL);
+                  eina_hash_add(*font_hash, font, efp);
+               }
+          }
+     }
+   return efp;
+}
+
+/* FIXME: do we really need it? */
+Eina_Hash *
+_elm_font_available_hash_add(Eina_Hash  *font_hash,
+                             const char *full_name)
+{
+   _elm_font_properties_get(&font_hash, full_name);
+   return font_hash;
+}
+
+static void
+_elm_font_properties_free(Elm_Font_Properties *efp)
+{
+   const char *str;
+
+   EINA_LIST_FREE(efp->styles, str)
+     if (str) eina_stringshare_del(str);
+
+   if (efp->name) eina_stringshare_del(efp->name);
+   free(efp);
+}
+
+static Eina_Bool
+_font_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
+{
+   Elm_Font_Properties *efp;
+
+   efp = data;
+   _elm_font_properties_free(efp);
+   return EINA_TRUE;
+}
+
+void
+_elm_font_available_hash_del(Eina_Hash *hash)
+{
+   eina_hash_foreach(hash, _font_hash_free_cb, NULL);
+   eina_hash_free(hash);
+}
diff --git a/src/lib/elm_frame.c b/src/lib/elm_frame.c
new file mode 100644 (file)
index 0000000..0e00a12
--- /dev/null
@@ -0,0 +1,251 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Frame Frame
+ *
+ * This holds some content and has a title. Looks like a frame, but
+ * supports styles so multple frames are avaible
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *frm;
+   Evas_Object *content;
+   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->frm, "frame", "base", elm_widget_style_get(obj));
+   edje_object_part_text_set(wd->frm, "elm.text", wd->label);
+   if (wd->content)
+     edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content);
+   edje_object_scale_set(wd->frm, elm_widget_scale_get(obj) * _elm_config->scale);
+   _sizing_eval(obj);
+}
+
+static Eina_Bool
+_elm_frame_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *cur;
+
+   if ((!wd) || (!wd->content))
+     return EINA_FALSE;
+
+   cur = wd->content;
+
+   /* Try Focus cycle in subitem */
+   return elm_widget_focus_next_get(cur, dir, next);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   if (!wd) return;
+   edje_object_size_min_calc(wd->frm, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+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);
+   // FIXME: why is this needed? how does edje get this unswallowed or
+   // lose its callbacks to edje
+   if (!wd) return;
+   edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content);
+   _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;
+   if (sub == wd->content)
+     {
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       wd->content = NULL;
+       _sizing_eval(obj);
+     }
+}
+
+/**
+ * Add a new frame to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Frame
+ */
+EAPI Evas_Object *
+elm_frame_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "frame");
+   elm_widget_type_set(obj, "frame");
+   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_focus_next_hook_set(obj, _elm_frame_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->frm = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->frm, "frame", "base", "default");
+   elm_widget_resize_object_set(obj, wd->frm);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the frame label
+ *
+ * @param obj The frame object
+ * @param label The label of this frame object
+ *
+ * @ingroup Frame
+ */
+EAPI void
+elm_frame_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->frm, "elm.text", wd->label);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the frame label
+ *
+ * @param obj The frame object
+ *
+ * @return The label of this frame objet or NULL if unable to get frame
+ *
+ * @ingroup Frame
+ */
+EAPI const char *
+elm_frame_label_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->label;
+}
+
+/**
+ * Set the content of the frame widget
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_frame_content_unset() function.
+ *
+ * @param obj The frame object
+ * @param content The content will be filled in this frame object
+ *
+ * @ingroup Frame
+ */
+EAPI void
+elm_frame_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content) evas_object_del(wd->content);
+   wd->content = content;
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+       evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->frm, "elm.swallow.content", content);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the content of the frame widget
+ *
+ * Return the content object which is set for this widget
+ *
+ * @param obj The frame object
+ * @return The content that is being used
+ *
+ * @ingroup Frame
+ */
+EAPI Evas_Object *
+elm_frame_content_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->content;
+}
+
+/**
+ * Unset the content of the frame widget
+ *
+ * Unparent and return the content object which was set for this widget
+ *
+ * @param obj The frame object
+ * @return The content that was being used
+ *
+ * @ingroup Frame
+ */
+EAPI Evas_Object *
+elm_frame_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *content;
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   content = wd->content;
+   elm_widget_sub_object_del(obj, wd->content);
+   edje_object_part_unswallow(wd->frm, wd->content);
+   wd->content = NULL;
+   return content;
+}
diff --git a/src/lib/elm_gengrid.c b/src/lib/elm_gengrid.c
new file mode 100644 (file)
index 0000000..0060898
--- /dev/null
@@ -0,0 +1,2904 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Gengrid Gengrid
+ *
+ * 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 item, 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 item. The event_info
+ * parameter is the Gengrid item that was double-clicked.
+ *
+ * selected - The user has made an item selected. The event_info
+ * parameter is the Gengrid item that was selected.
+ *
+ * unselected - The user has made an item unselected. The event_info
+ * parameter is the Gengrid item that was unselected.
+ *
+ * realized - This is called when the item in the Gengrid is created
+ * as a real evas object. event_info is the Gengrid item 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_gengrid_item_object_get() in a way where it may point to freed
+ * objects.
+ *
+ * unrealized - This is called when the real evas object for this item
+ * is deleted. event_info is the Gengrid item that was created.
+ *
+ * changed - Called when an item is added, removed, resized or moved
+ * and when gengrid is resized or horizontal property changes.
+ *
+ * drag,start,up - Called when the item in the Gengrid has been
+ * dragged (not scrolled) up.
+ *
+ * drag,start,down - Called when the item in the Gengrid has been
+ * dragged (not scrolled) down.
+ *
+ * drag,start,left - Called when the item in the Gengrid has been
+ * dragged (not scrolled) left.
+ *
+ * drag,start,right - Called when the item in the Gengrid has been
+ * dragged (not scrolled) right.
+ *
+ * drag,stop - Called when the item in the Gengrid has stopped being
+ * dragged.
+ *
+ * drag - Called when the item in the Gengrid 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 item in the Gengrid 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 Gengrid
+ * item) and 0 or more boolean states that can be used for check,
+ * radio or other indicators by the edje theme style.  A item 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 items on the
+ * fly, Gengrid implements a class/callback system where the
+ * application provides a structure with information about that type
+ * of item (Gengrid may contain multiple different items with
+ * different classes, states and styles). Gengrid will call the
+ * functions in this struct (methods) when a item is "realized" (that
+ * is created dynamically while scrolling). All objects will simply be
+ * deleted when no longer needed with evas_object_del(). The
+ * Elm_GenGrid_Item_Class structure contains the following members:
+ *
+ * item_style - This is a constant string and simply defines the name
+ * of the item style. It must be specified and the default should be
+ * "default".
+ *
+ * func.label_get - This function is called when an actual item object
+ * is created. The data parameter is the one passed to
+ * elm_gengrid_item_append() and related item creation functions. The
+ * obj parameter is the Gengrid 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_gengrid_item_append() and related item creation functions. The
+ * obj parameter is the Gengrid 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
+ * Gengrid on shutdown or when the item is unrealized.
+ *
+ * func.state_get - This function is called when an actual item object
+ * is created. The data parameter is the one passed to
+ * elm_gengrid_item_append() and related item creation functions. The
+ * obj parameter is the Gengrid 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. Gengrid 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_gengrid_item_del() is called on
+ * a item or elm_gengrid_clear() is called on the Gengrid. This is
+ * intended for use when actual Gengrid items are deleted, so any
+ * backing data attached to the item (e.g. its data parameter on
+ * creation) can be deleted.
+ *
+ * If the application wants multiple items to be able to be selected,
+ * elm_gengrid_multi_select_set() can enable this. If the Gengrid is
+ * single-selection only (the default), then
+ * elm_gengrid_select_item_get() will return the selected item, if
+ * any, or NULL if none is selected. If the Gengrid is multi-select
+ * then elm_gengrid_selected_items_get() will return a list (that is
+ * only valid as long as no items are modified (added, deleted,
+ * selected or unselected).
+ *
+ * If a item changes (state of boolean changes, label or icons
+ * change), then use elm_gengrid_item_update() to have Gengrid update
+ * the item with the new state. Gengrid will re-realize the item thus
+ * call the functions in the _Elm_Gengrid_Item_Class for that item.
+ *
+ * To programmatically (un)select a item use
+ * elm_gengrid_item_selected_set().  To get its selected state use
+ * elm_gengrid_item_selected_get(). To make a item disabled (unable to
+ * be selected and appear differently) use
+ * elm_gengrid_item_disabled_set() to set this and
+ * elm_gengrid_item_disabled_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_gengrid_always_select_mode_set(). This means event if selected,
+ * every click will make the selected callbacks be called.
+ * elm_gengrid_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_Gengrid_Item
+{
+   Elm_Widget_Item               base;
+   EINA_INLIST;
+   Evas_Object                  *spacer;
+   const Elm_Gengrid_Item_Class *gic;
+   Ecore_Timer                  *long_timer;
+   Widget_Data                  *wd;
+   Eina_List                    *labels, *icons, *states, *icon_objs;
+   struct
+   {
+      Evas_Smart_Cb func;
+      const void   *data;
+   } func;
+
+   Evas_Coord x, y, dx, dy;
+   int        relcount;
+   int        walking;
+
+   struct
+   {
+      const void                 *data;
+      Elm_Tooltip_Item_Content_Cb content_cb;
+      Evas_Smart_Cb               del_cb;
+      const char                 *style;
+   } tooltip;
+
+   const char *mouse_cursor;
+
+   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;
+};
+
+struct _Widget_Data
+{
+   Evas_Object      *self, *scr;
+   Evas_Object      *pan_smart;
+   Pan              *pan;
+   Eina_Inlist      *items;
+   Ecore_Job        *calc_job;
+   Eina_List        *selected;
+   Elm_Gengrid_Item *last_selected_item;
+   double            align_x, align_y;
+
+   Evas_Coord        pan_x, pan_y;
+   Evas_Coord        item_width, item_height; /* Each item size */
+   Evas_Coord        minw, minh; /* Total obj size */
+   unsigned int      nmax;
+   long              count;
+   int               walking;
+
+   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;
+   Eina_Bool         clear_me : 1;
+};
+
+#define ELM_GENGRID_ITEM_FROM_INLIST(item) \
+  ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Gengrid_Item) : NULL)
+
+struct _Pan
+{
+   Evas_Object_Smart_Clipped_Data __clipped_data;
+   Widget_Data                   *wd;
+};
+
+static const char *widtype = NULL;
+static void      _item_hilight(Elm_Gengrid_Item *item);
+static void      _item_unrealize(Elm_Gengrid_Item *item);
+static void      _item_select(Elm_Gengrid_Item *item);
+static void      _item_unselect(Elm_Gengrid_Item *item);
+static void      _calc_job(void *data);
+static void      _on_focus_hook(void        *data,
+                                Evas_Object *obj);
+static Eina_Bool _item_multi_select_up(Widget_Data *wd);
+static Eina_Bool _item_multi_select_down(Widget_Data *wd);
+static Eina_Bool _item_multi_select_left(Widget_Data *wd);
+static Eina_Bool _item_multi_select_right(Widget_Data *wd);
+static Eina_Bool _item_single_select_up(Widget_Data *wd);
+static Eina_Bool _item_single_select_down(Widget_Data *wd);
+static Eina_Bool _item_single_select_left(Widget_Data *wd);
+static Eina_Bool _item_single_select_right(Widget_Data *wd);
+static Eina_Bool _event_hook(Evas_Object       *obj,
+                             Evas_Object       *src,
+                             Evas_Callback_Type type,
+                             void              *event_info);
+static Eina_Bool _deselect_all_items(Widget_Data *wd);
+
+static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
+
+static Eina_Bool
+_event_hook(Evas_Object       *obj,
+            Evas_Object *src   __UNUSED__,
+            Evas_Callback_Type type,
+            void              *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (!wd->items) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   Elm_Gengrid_Item *item = NULL;
+   Evas_Coord x = 0;
+   Evas_Coord y = 0;
+   Evas_Coord step_x = 0;
+   Evas_Coord step_y = 0;
+   Evas_Coord v_w = 0;
+   Evas_Coord v_h = 0;
+   Evas_Coord page_x = 0;
+   Evas_Coord page_y = 0;
+
+   elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
+   elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
+   elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
+
+   if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
+     {
+        if ((wd->horizontal) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_up(wd)))
+             || (_item_single_select_up(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if ((!wd->horizontal) &&
+                 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+                   (_item_multi_select_left(wd)))
+                  || (_item_single_select_left(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          x -= step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
+     {
+        if ((wd->horizontal) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_down(wd)))
+             || (_item_single_select_down(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if ((!wd->horizontal) &&
+                 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+                   (_item_multi_select_right(wd)))
+                  || (_item_single_select_right(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          x += step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
+     {
+        if ((wd->horizontal) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_left(wd)))
+             || (_item_single_select_left(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if ((!wd->horizontal) &&
+                 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+                   (_item_multi_select_up(wd)))
+                  || (_item_single_select_up(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          y -= step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
+     {
+        if ((wd->horizontal) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_right(wd)))
+             || (_item_single_select_right(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if ((!wd->horizontal) &&
+                 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+                   (_item_multi_select_down(wd)))
+                  || (_item_single_select_down(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          y += step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
+     {
+        item = elm_gengrid_first_item_get(obj);
+        elm_gengrid_item_bring_in(item);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
+     {
+        item = elm_gengrid_last_item_get(obj);
+        elm_gengrid_item_bring_in(item);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "Prior")) ||
+            (!strcmp(ev->keyname, "KP_Prior")))
+     {
+        if (wd->horizontal)
+          {
+             if (page_x < 0)
+               x -= -(page_x * v_w) / 100;
+             else
+               x -= page_x;
+          }
+        else
+          {
+             if (page_y < 0)
+               y -= -(page_y * v_h) / 100;
+             else
+               y -= page_y;
+          }
+     }
+   else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
+     {
+        if (wd->horizontal)
+          {
+             if (page_x < 0)
+               x += -(page_x * v_w) / 100;
+             else
+               x += page_x;
+          }
+        else
+          {
+             if (page_y < 0)
+               y += -(page_y * v_h) / 100;
+             else
+               y += page_y;
+          }
+     }
+   else if (!strcmp(ev->keyname, "Escape"))
+     {
+        if (!_deselect_all_items(wd)) return EINA_FALSE;
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else return EINA_FALSE;
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   elm_smart_scroller_child_pos_set(wd->scr, x, y);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_deselect_all_items(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   while(wd->selected)
+     elm_gengrid_item_selected_set(wd->selected->data, EINA_FALSE);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_left(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+
+   Elm_Gengrid_Item *prev = elm_gengrid_item_prev_get(wd->last_selected_item);
+   if (!prev) return EINA_TRUE;
+   if (elm_gengrid_item_selected_get(prev))
+     {
+        elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = prev;
+        elm_gengrid_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_gengrid_item_selected_set(prev, EINA_TRUE);
+        elm_gengrid_item_show(prev);
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_right(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+
+   Elm_Gengrid_Item *next = elm_gengrid_item_next_get(wd->last_selected_item);
+   if (!next) return EINA_TRUE;
+   if (elm_gengrid_item_selected_get(next))
+     {
+        elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = next;
+        elm_gengrid_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_gengrid_item_selected_set(next, EINA_TRUE);
+        elm_gengrid_item_show(next);
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_up(Widget_Data *wd)
+{
+   unsigned int i;
+   Eina_Bool r = EINA_TRUE;
+
+   if (!wd->selected) return EINA_FALSE;
+
+   for (i = 0; (r) && (i < wd->nmax); i++)
+     r &= _item_multi_select_left(wd);
+
+   return r;
+}
+
+static Eina_Bool
+_item_multi_select_down(Widget_Data *wd)
+{
+   unsigned int i;
+   Eina_Bool r = EINA_TRUE;
+
+   if (!wd->selected) return EINA_FALSE;
+
+   for (i = 0; (r) && (i < wd->nmax); i++)
+     r &= _item_multi_select_right(wd);
+
+   return r;
+}
+
+static Eina_Bool
+_item_single_select_up(Widget_Data *wd)
+{
+   unsigned int i;
+
+   Elm_Gengrid_Item *prev;
+
+   if (!wd->selected)
+     {
+        prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
+        while ((prev) && (prev->delete_me))
+          prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
+        elm_gengrid_item_selected_set(prev, EINA_TRUE);
+        elm_gengrid_item_show(prev);
+        return EINA_TRUE;
+     }
+   else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
+
+   if (!prev) return EINA_FALSE;
+
+   for (i = 1; i < wd->nmax; i++)
+     {
+        Elm_Gengrid_Item *tmp = elm_gengrid_item_prev_get(prev);
+        if (!tmp) return EINA_FALSE;
+        prev = tmp;
+     }
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(prev, EINA_TRUE);
+   elm_gengrid_item_show(prev);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_down(Widget_Data *wd)
+{
+   unsigned int i;
+
+   Elm_Gengrid_Item *next;
+
+   if (!wd->selected)
+     {
+        next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
+        while ((next) && (next->delete_me))
+          next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
+        elm_gengrid_item_selected_set(next, EINA_TRUE);
+        elm_gengrid_item_show(next);
+        return EINA_TRUE;
+     }
+   else next = elm_gengrid_item_next_get(wd->last_selected_item);
+
+   if (!next) return EINA_FALSE;
+
+   for (i = 1; i < wd->nmax; i++)
+     {
+        Elm_Gengrid_Item *tmp = elm_gengrid_item_next_get(next);
+        if (!tmp) return EINA_FALSE;
+        next = tmp;
+     }
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(next, EINA_TRUE);
+   elm_gengrid_item_show(next);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_left(Widget_Data *wd)
+{
+   Elm_Gengrid_Item *prev;
+   if (!wd->selected)
+     {
+        prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
+        while ((prev) && (prev->delete_me))
+          prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
+     }
+   else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
+
+   if (!prev) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(prev, EINA_TRUE);
+   elm_gengrid_item_show(prev);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_right(Widget_Data *wd)
+{
+   Elm_Gengrid_Item *next;
+   if (!wd->selected)
+     {
+        next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
+        while ((next) && (next->delete_me))
+          next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
+     }
+   else next = elm_gengrid_item_next_get(wd->last_selected_item);
+
+   if (!next) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_gengrid_item_selected_set(next, EINA_TRUE);
+   elm_gengrid_item_show(next);
+   return EINA_TRUE;
+}
+
+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))
+     {
+        edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
+        evas_object_focus_set(wd->self, EINA_TRUE);
+        if ((wd->selected) && (!wd->last_selected_item))
+          wd->last_selected_item = eina_list_data_get(wd->selected);
+     }
+   else
+     {
+        edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
+        evas_object_focus_set(wd->self, EINA_FALSE);
+     }
+}
+
+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, "gengrid", "base",
+                                       elm_widget_style_get(obj));
+}
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_gengrid_clear(obj);
+   evas_object_del(wd->pan_smart);
+   wd->pan_smart = NULL;
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   free(wd);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj,
+                  const char  *emission,
+                  const char  *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                           emission, source);
+}
+
+static void
+_mouse_move(void        *data,
+            Evas *evas   __UNUSED__,
+            Evas_Object *obj,
+            void        *event_info)
+{
+   Elm_Gengrid_Item *item = 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 (!item->wd->on_hold)
+          {
+             item->wd->on_hold = EINA_TRUE;
+             if (!item->wd->wasselected)
+               _item_unselect(item);
+          }
+     }
+   if ((item->dragging) && (item->down))
+     {
+        if (item->long_timer)
+          {
+             ecore_timer_del(item->long_timer);
+             item->long_timer = NULL;
+          }
+        evas_object_smart_callback_call(item->wd->self, "drag", item);
+        return;
+     }
+   if ((!item->down) || (item->wd->longpressed))
+     {
+        if (item->long_timer)
+          {
+             ecore_timer_del(item->long_timer);
+             item->long_timer = NULL;
+          }
+        return;
+     }
+   if (!item->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 - item->dx;
+   adx = dx;
+   if (adx < 0) adx = -dx;
+   dy = y - item->dy;
+   ady = dy;
+   if (ady < 0) ady = -dy;
+   minw /= 2;
+   minh /= 2;
+   if ((adx > minw) || (ady > minh))
+     {
+        item->dragging = 1;
+        if (item->long_timer)
+          {
+             ecore_timer_del(item->long_timer);
+             item->long_timer = NULL;
+          }
+        if (!item->wd->wasselected)
+          _item_unselect(item);
+        if (dy < 0)
+          {
+             if (ady > adx)
+               evas_object_smart_callback_call(item->wd->self, "drag,start,up",
+                                               item);
+             else
+               {
+                  if (dx < 0)
+                    evas_object_smart_callback_call(item->wd->self,
+                                                    "drag,start,left", item);
+               }
+          }
+        else
+          {
+             if (ady > adx)
+               evas_object_smart_callback_call(item->wd->self,
+                                               "drag,start,down", item);
+             else
+               {
+                  if (dx < 0)
+                    evas_object_smart_callback_call(item->wd->self,
+                                                    "drag,start,left", item);
+                  else
+                    evas_object_smart_callback_call(item->wd->self,
+                                                    "drag,start,right", item);
+               }
+          }
+     }
+}
+
+static Eina_Bool
+_long_press(void *data)
+{
+   Elm_Gengrid_Item *item = data;
+
+   item->long_timer = NULL;
+   if ((item->disabled) || (item->dragging)) return ECORE_CALLBACK_CANCEL;
+   item->wd->longpressed = EINA_TRUE;
+   evas_object_smart_callback_call(item->wd->self, "longpressed", item);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_mouse_down(void        *data,
+            Evas *evas   __UNUSED__,
+            Evas_Object *obj,
+            void        *event_info)
+{
+   Elm_Gengrid_Item *item = data;
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord x, y;
+
+   if (ev->button != 1) return;
+   item->down = 1;
+   item->dragging = 0;
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   item->dx = ev->canvas.x - x;
+   item->dy = ev->canvas.y - y;
+   item->wd->longpressed = EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) item->wd->on_hold = EINA_TRUE;
+   else item->wd->on_hold = EINA_FALSE;
+   item->wd->wasselected = item->selected;
+   _item_hilight(item);
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     evas_object_smart_callback_call(item->wd->self, "clicked", item);
+   if (item->long_timer) ecore_timer_del(item->long_timer);
+   if (item->realized)
+     item->long_timer = ecore_timer_add(_elm_config->longpress_timeout,
+                                        _long_press, item);
+   else
+     item->long_timer = NULL;
+}
+
+static void
+_mouse_up(void            *data,
+          Evas *evas       __UNUSED__,
+          Evas_Object *obj __UNUSED__,
+          void            *event_info)
+{
+   Elm_Gengrid_Item *item = data;
+   Evas_Event_Mouse_Up *ev = event_info;
+   Eina_Bool dragged = EINA_FALSE;
+
+   if (ev->button != 1) return;
+   item->down = EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) item->wd->on_hold = EINA_TRUE;
+   else item->wd->on_hold = EINA_FALSE;
+   if (item->long_timer)
+     {
+        ecore_timer_del(item->long_timer);
+        item->long_timer = NULL;
+     }
+   if (item->dragging)
+     {
+        item->dragging = EINA_FALSE;
+        evas_object_smart_callback_call(item->wd->self, "drag,stop", item);
+        dragged = EINA_TRUE;
+     }
+   if (item->wd->on_hold)
+     {
+        item->wd->longpressed = EINA_FALSE;
+        item->wd->on_hold = EINA_FALSE;
+        return;
+     }
+   if (item->wd->longpressed)
+     {
+        item->wd->longpressed = EINA_FALSE;
+        if (!item->wd->wasselected) _item_unselect(item);
+        item->wd->wasselected = EINA_FALSE;
+        return;
+     }
+   if (dragged)
+     {
+        if (item->want_unrealize) _item_unrealize(item);
+     }
+   if ((item->disabled) || (dragged)) return;
+   if (item->wd->multi)
+     {
+        if (!item->selected)
+          {
+             _item_hilight(item);
+             _item_select(item);
+          }
+        else _item_unselect(item);
+     }
+   else
+     {
+        if (!item->selected)
+          {
+             while (item->wd->selected)
+               _item_unselect(item->wd->selected->data);
+          }
+        else
+          {
+             const Eina_List *l, *l_next;
+             Elm_Gengrid_Item *item2;
+
+             EINA_LIST_FOREACH_SAFE(item->wd->selected, l, l_next, item2)
+               if (item2 != item) _item_unselect(item2);
+          }
+        _item_hilight(item);
+        _item_select(item);
+     }
+}
+
+static void
+_item_hilight(Elm_Gengrid_Item *item)
+{
+   if ((item->wd->no_select) || (item->delete_me) || (item->hilighted)) return;
+   edje_object_signal_emit(item->base.view, "elm,state,selected", "elm");
+   item->hilighted = EINA_TRUE;
+}
+
+static void
+_item_realize(Elm_Gengrid_Item *item)
+{
+   char buf[1024];
+   char style[1024];
+
+   if ((item->realized) || (item->delete_me)) return;
+   item->base.view = edje_object_add(evas_object_evas_get(item->wd->self));
+   edje_object_scale_set(item->base.view, elm_widget_scale_get(item->wd->self) *
+                         _elm_config->scale);
+   evas_object_smart_member_add(item->base.view, item->wd->pan_smart);
+   elm_widget_sub_object_add(item->wd->self, item->base.view);
+   snprintf(style, sizeof(style), "item/%s",
+            item->gic->item_style ? item->gic->item_style : "default");
+   _elm_theme_object_set(item->wd->self, item->base.view, "gengrid", style,
+                         elm_widget_style_get(item->wd->self));
+   item->spacer =
+       evas_object_rectangle_add(evas_object_evas_get(item->wd->self));
+   evas_object_color_set(item->spacer, 0, 0, 0, 0);
+   elm_widget_sub_object_add(item->wd->self, item->spacer);
+   evas_object_size_hint_min_set(item->spacer, 2 * _elm_config->scale, 1);
+   edje_object_part_swallow(item->base.view, "elm.swallow.pad", item->spacer);
+
+   if (item->gic->func.label_get)
+     {
+        const Eina_List *l;
+        const char *key;
+
+        item->labels =
+            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
+                                                           "labels"));
+        EINA_LIST_FOREACH(item->labels, l, key)
+          {
+             char *s = item->gic->func.label_get
+                 ((void *)item->base.data, item->wd->self, l->data);
+             if (s)
+               {
+                  edje_object_part_text_set(item->base.view, l->data, s);
+                  free(s);
+               }
+          }
+     }
+
+   if (item->gic->func.icon_get)
+     {
+        const Eina_List *l;
+        const char *key;
+
+        item->icons =
+            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
+                                                           "icons"));
+        EINA_LIST_FOREACH(item->icons, l, key)
+          {
+             Evas_Object *ic = item->gic->func.icon_get
+                 ((void *)item->base.data, item->wd->self, l->data);
+             if (ic)
+               {
+                  item->icon_objs = eina_list_append(item->icon_objs, ic);
+                  edje_object_part_swallow(item->base.view, key, ic);
+                  evas_object_show(ic);
+                  elm_widget_sub_object_add(item->wd->self, ic);
+               }
+          }
+     }
+
+   if (item->gic->func.state_get)
+     {
+        const Eina_List *l;
+        const char *key;
+
+        item->states =
+            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
+                                                           "states"));
+        EINA_LIST_FOREACH(item->states, l, key)
+          {
+             Eina_Bool on = item->gic->func.state_get
+                 ((void *)item->base.data, item->wd->self, l->data);
+             if (on)
+               {
+                  snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
+                  edje_object_signal_emit(item->base.view, buf, "elm");
+               }
+          }
+     }
+
+   if ((!item->wd->item_width) && (!item->wd->item_height))
+     {
+        edje_object_size_min_restricted_calc(item->base.view,
+                                             &item->wd->item_width,
+                                             &item->wd->item_height,
+                                             item->wd->item_width,
+                                             item->wd->item_height);
+        elm_coords_finger_size_adjust(1, &item->wd->item_width,
+                                      1, &item->wd->item_height);
+     }
+
+   evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _mouse_down, item);
+   evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_UP,
+                                  _mouse_up, item);
+   evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _mouse_move, item);
+
+   if (item->selected)
+     edje_object_signal_emit(item->base.view, "elm,state,selected", "elm");
+   if (item->disabled)
+     edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
+
+   evas_object_show(item->base.view);
+
+   if (item->tooltip.content_cb)
+     {
+        elm_widget_item_tooltip_content_cb_set(item,
+                                               item->tooltip.content_cb,
+                                               item->tooltip.data, NULL);
+        elm_widget_item_tooltip_style_set(item, item->tooltip.style);
+     }
+
+   if (item->mouse_cursor)
+     elm_widget_item_cursor_set(item, item->mouse_cursor);
+
+   item->realized = EINA_TRUE;
+   item->want_unrealize = EINA_FALSE;
+}
+
+static void
+_item_unrealize(Elm_Gengrid_Item *item)
+{
+   Evas_Object *icon;
+
+   if (!item->realized) return;
+   if (item->long_timer)
+     {
+        ecore_timer_del(item->long_timer);
+        item->long_timer = NULL;
+     }
+   evas_object_del(item->base.view);
+   item->base.view = NULL;
+   evas_object_del(item->spacer);
+   item->spacer = NULL;
+   elm_widget_stringlist_free(item->labels);
+   item->labels = NULL;
+   elm_widget_stringlist_free(item->icons);
+   item->icons = NULL;
+   elm_widget_stringlist_free(item->states);
+   item->states = NULL;
+
+   EINA_LIST_FREE(item->icon_objs, icon)
+     evas_object_del(icon);
+
+   item->realized = EINA_FALSE;
+   item->want_unrealize = EINA_FALSE;
+}
+
+static void
+_item_place(Elm_Gengrid_Item *item,
+            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;
+
+   item->x = cx;
+   item->y = cy;
+   evas_object_geometry_get(item->wd->pan_smart, &ox, &oy, &vw, &vh);
+
+   /* Preload rows/columns at each side of the Gengrid */
+   cvx = ox - PRELOAD * item->wd->item_width;
+   cvy = oy - PRELOAD * item->wd->item_height;
+   cvw = vw + 2 * PRELOAD * item->wd->item_width;
+   cvh = vh + 2 * PRELOAD * item->wd->item_height;
+
+   alignh = 0;
+   alignw = 0;
+
+   if (item->wd->horizontal)
+     {
+        int columns, items_visible = 0, items_row;
+
+        if (item->wd->item_height > 0)
+          items_visible = vh / item->wd->item_height;
+        if (items_visible < 1)
+          items_visible = 1;
+
+        columns = item->wd->count / items_visible;
+        if (item->wd->count % items_visible)
+          columns++;
+
+        tcw = item->wd->item_width * columns;
+        alignw = (vw - tcw) * item->wd->align_x;
+
+        items_row = items_visible;
+        if (items_row > item->wd->count)
+          items_row = item->wd->count;
+        tch = items_row * item->wd->item_height;
+        alignh = (vh - tch) * item->wd->align_y;
+     }
+   else
+     {
+        int rows, items_visible = 0, items_col;
+
+        if (item->wd->item_width > 0)
+          items_visible = vw / item->wd->item_width;
+        if (items_visible < 1)
+          items_visible = 1;
+
+        rows = item->wd->count / items_visible;
+        if (item->wd->count % items_visible)
+          rows++;
+
+        tch = item->wd->item_height * rows;
+        alignh = (vh - tch) * item->wd->align_y;
+
+        items_col = items_visible;
+        if (items_col > item->wd->count)
+          items_col = item->wd->count;
+        tcw = items_col * item->wd->item_width;
+        alignw = (vw - tcw) * item->wd->align_x;
+     }
+
+   x = cx * item->wd->item_width - item->wd->pan_x + ox + alignw;
+   y = cy * item->wd->item_height - item->wd->pan_y + oy + alignh;
+
+   Eina_Bool was_realized = item->realized;
+   if (ELM_RECTS_INTERSECT(x, y, item->wd->item_width, item->wd->item_height,
+                           cvx, cvy, cvw, cvh))
+     {
+        _item_realize(item);
+        if (!was_realized)
+          evas_object_smart_callback_call(item->wd->self, "realized", item);
+        evas_object_move(item->base.view, x, y);
+        evas_object_resize(item->base.view, item->wd->item_width,
+                           item->wd->item_height);
+     }
+   else
+     {
+        _item_unrealize(item);
+        if (was_realized)
+          evas_object_smart_callback_call(item->wd->self, "unrealized", item);
+     }
+}
+
+static Elm_Gengrid_Item *
+_item_create(Widget_Data                  *wd,
+             const Elm_Gengrid_Item_Class *gic,
+             const void                   *data,
+             Evas_Smart_Cb                 func,
+             const void                   *func_data)
+{
+   Elm_Gengrid_Item *item;
+
+   item = elm_widget_item_new(wd->self, Elm_Gengrid_Item);
+   if (!item) return NULL;
+   wd->count++;
+   item->wd = wd;
+   item->gic = gic;
+   item->base.data = data;
+   item->func.func = func;
+   item->func.data = func_data;
+   item->mouse_cursor = NULL;
+   return item;
+}
+
+static void
+_item_del(Elm_Gengrid_Item *item)
+{
+   elm_widget_item_pre_notify_del(item);
+   if (item->selected)
+     item->wd->selected = eina_list_remove(item->wd->selected, item);
+   if (item->realized) _item_unrealize(item);
+   if ((!item->delete_me) && (item->gic->func.del))
+     item->gic->func.del((void *)item->base.data, item->wd->self);
+   item->delete_me = EINA_TRUE;
+   item->wd->items = eina_inlist_remove(item->wd->items, EINA_INLIST_GET(item));
+   if (item->long_timer) ecore_timer_del(item->long_timer);
+   if (item->tooltip.del_cb)
+     item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
+   item->wd->walking -= item->walking;
+   item->wd->count--;
+   if (item->wd->calc_job) ecore_job_del(item->wd->calc_job);
+   item->wd->calc_job = ecore_job_add(_calc_job, item->wd);
+   elm_widget_item_del(item);
+}
+
+static void
+_item_select(Elm_Gengrid_Item *item)
+{
+   if ((item->wd->no_select) || (item->delete_me)) return;
+   if (item->selected)
+     {
+        if (item->wd->always_select) goto call;
+        return;
+     }
+   item->selected = EINA_TRUE;
+   item->wd->selected = eina_list_append(item->wd->selected, item);
+call:
+   item->walking++;
+   item->wd->walking++;
+   if (item->func.func)
+     item->func.func((void *)item->func.data, item->wd->self, item);
+   if (!item->delete_me)
+     evas_object_smart_callback_call(item->wd->self, "selected", item);
+   item->walking--;
+   item->wd->walking--;
+   if ((item->wd->clear_me) && (!item->wd->walking))
+     elm_gengrid_clear(item->base.widget);
+   else
+     {
+        if ((!item->walking) && (item->delete_me))
+          if (!item->relcount) _item_del(item);
+     }
+   item->wd->last_selected_item = item;
+}
+
+static void
+_item_unselect(Elm_Gengrid_Item *item)
+{
+   if ((item->delete_me) || (!item->hilighted)) return;
+   edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm");
+   item->hilighted = EINA_FALSE;
+   if (item->selected)
+     {
+        item->selected = EINA_FALSE;
+        item->wd->selected = eina_list_remove(item->wd->selected, item);
+        evas_object_smart_callback_call(item->wd->self, "unselected", item);
+     }
+}
+
+static void
+_calc_job(void *data)
+{
+   Widget_Data *wd = data;
+   Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
+   int count;
+
+   evas_object_geometry_get(wd->pan_smart, NULL, NULL, &cvw, &cvh);
+   if ((wd->horizontal) && (wd->item_height > 0))
+     nmax = cvh / wd->item_height;
+   else if (wd->item_width > 0)
+     nmax = cvw / wd->item_width;
+
+   if (nmax < 1)
+     nmax = 1;
+
+   count = wd->count;
+   if (wd->horizontal)
+     {
+        minw = ceil(count / (float)nmax) * wd->item_width;
+        minh = nmax * wd->item_height;
+     }
+   else
+     {
+        minw = nmax * wd->item_width;
+        minh = ceil(count / (float)nmax) * wd->item_height;
+     }
+
+   if ((minw != wd->minw) || (minh != wd->minh))
+     {
+        wd->minh = minh;
+        wd->minw = minw;
+        evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
+     }
+
+   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_min_get(Evas_Object *obj,
+             Evas_Coord  *x,
+             Evas_Coord  *y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   Evas_Coord mx, my;
+
+   if (!sd) return;
+   _pan_max_get(obj, &mx, &my);
+   if (x)
+     *x = -mx * sd->wd->align_x;
+   if (y)
+     *y = -my * sd->wd->align_y;
+}
+
+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;
+   Elm_Gengrid_Item *item;
+
+   if (!sd) return;
+   if (!sd->wd->nmax) return;
+
+   EINA_INLIST_FOREACH(sd->wd->items, item)
+   {
+      _item_place(item, 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++;
+        }
+   }
+   evas_object_smart_callback_call(sd->wd->self, "changed", NULL);
+}
+
+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 Gengrid object.
+ *
+ * @param parent The parent object.
+ * @return  The new object or NULL if it cannot be created.
+ *
+ * @see elm_gengrid_item_size_set()
+ * @see elm_gengrid_horizontal_set()
+ * @see elm_gengrid_item_append()
+ * @see elm_gengrid_item_del()
+ * @see elm_gengrid_clear()
+ *
+ * @ingroup Gengrid
+ */
+EAPI Evas_Object *
+elm_gengrid_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   static Evas_Smart *smart = NULL;
+   Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "gengrid");
+   elm_widget_type_set(obj, "gengrid");
+   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_del_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_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, "gengrid", "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, bounce, bounce);
+
+   wd->self = obj;
+   wd->align_x = 0.5;
+   wd->align_y = 0.5;
+   wd->no_select = EINA_FALSE;
+
+   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_gengrid_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_min_get, _pan_child_size_get);
+
+   return obj;
+}
+
+/**
+ * Set the size for the item of the Gengrid.
+ *
+ * @param obj The Gengrid object.
+ * @param w The item's width.
+ * @param h The item's height;
+ *
+ * @see elm_gengrid_item_size_get()
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_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->item_width == w) && (wd->item_height == h)) return;
+   wd->item_width = w;
+   wd->item_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 item of the Gengrid.
+ *
+ * @param obj The Gengrid object.
+ * @param w Pointer to the item's width.
+ * @param h Pointer to the item's height.
+ *
+ * @see elm_gengrid_item_size_get()
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_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->item_width;
+   if (h) *h = wd->item_height;
+}
+
+/**
+ * Set item's alignment within the scroller.
+ *
+ * @param obj The Gengrid object.
+ * @param align_x The x alignment (0 <= x <= 1).
+ * @param align_y The y alignment (0 <= y <= 1).
+ *
+ * @see elm_gengrid_align_get()
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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 Gengrid object.
+ *
+ * @param obj The Gengrid object.
+ * @param align_x Pointer to x alignenment.
+ * @param align_y Pointer to y alignenment.
+ *
+ * @see elm_gengrid_align_set()
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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 item to the end of the Gengrid.
+ *
+ * @param obj The Gengrid object.
+ * @param gic The item class for the item.
+ * @param data The item data.
+ * @param func Convenience function called when item is selected.
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible.
+ *
+ * @see elm_gengrid_item_prepend()
+ * @see elm_gengrid_item_insert_before()
+ * @see elm_gengrid_item_insert_after()
+ * @see elm_gengrid_item_del()
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_item_append(Evas_Object                  *obj,
+                        const Elm_Gengrid_Item_Class *gic,
+                        const void                   *data,
+                        Evas_Smart_Cb                 func,
+                        const void                   *func_data)
+{
+   Elm_Gengrid_Item *item;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   item = _item_create(wd, gic, data, func, func_data);
+   if (!item) return NULL;
+   wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(item));
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+
+   return item;
+}
+
+/**
+ * Add item at start of the Gengrid.
+ *
+ * This adds an item to the beginning of the grid.
+ *
+ * @param obj The Gengrid object.
+ * @param gic The item class for the item.
+ * @param data The item data.
+ * @param func Convenience function called when item is selected.
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible.
+ *
+ * @see elm_gengrid_item_append()
+ * @see elm_gengrid_item_insert_before()
+ * @see elm_gengrid_item_insert_after()
+ * @see elm_gengrid_item_del()
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_item_prepend(Evas_Object                  *obj,
+                         const Elm_Gengrid_Item_Class *gic,
+                         const void                   *data,
+                         Evas_Smart_Cb                 func,
+                         const void                   *func_data)
+{
+   Elm_Gengrid_Item *item;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   item = _item_create(wd, gic, data, func, func_data);
+   if (!item) return NULL;
+   wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(item));
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+
+   return item;
+}
+
+/**
+ * Insert and item before another in the Gengrid.
+ *
+ * This inserts an item before another in the grid.
+ *
+ * @param obj The Gengrid object.
+ * @param gic The item class for the item.
+ * @param data The item data.
+ * @param relative The item to which insert before.
+ * @param func Convenience function called when item is selected.
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible.
+ *
+ * @see elm_gengrid_item_append()
+ * @see elm_gengrid_item_prepend()
+ * @see elm_gengrid_item_insert_after()
+ * @see elm_gengrid_item_del()
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_item_insert_before(Evas_Object                  *obj,
+                               const Elm_Gengrid_Item_Class *gic,
+                               const void                   *data,
+                               Elm_Gengrid_Item             *relative,
+                               Evas_Smart_Cb                 func,
+                               const void                   *func_data)
+{
+   Elm_Gengrid_Item *item;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   item = _item_create(wd, gic, data, func, func_data);
+   if (!item) return NULL;
+   wd->items = eina_inlist_prepend_relative
+       (wd->items, EINA_INLIST_GET(item), EINA_INLIST_GET(relative));
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+
+   return item;
+}
+
+/**
+ * Insert and item after another in the Gengrid.
+ *
+ * This inserts an item after another in the grid.
+ *
+ * @param obj The Gengrid object.
+ * @param gic The item class for the item.
+ * @param data The item data.
+ * @param relative The item to which insert after.
+ * @param func Convenience function called when item is selected.
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible.
+ *
+ * @see elm_gengrid_item_append()
+ * @see elm_gengrid_item_prepend()
+ * @see elm_gengrid_item_insert_before()
+ * @see elm_gengrid_item_del()
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_item_insert_after(Evas_Object                  *obj,
+                              const Elm_Gengrid_Item_Class *gic,
+                              const void                   *data,
+                              Elm_Gengrid_Item             *relative,
+                              Evas_Smart_Cb                 func,
+                              const void                   *func_data)
+{
+   Elm_Gengrid_Item *item;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   item = _item_create(wd, gic, data, func, func_data);
+   if (!item) return NULL;
+   wd->items = eina_inlist_append_relative
+       (wd->items, EINA_INLIST_GET(item), EINA_INLIST_GET(relative));
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+
+   return item;
+}
+
+/**
+ * Remove a item from the Gengrid.
+ *
+ * @param item The item to be removed.
+ * @return @c EINA_TRUE on success or @c EINA_FALSE otherwise.
+ *
+ * @see elm_gengrid_clear() to remove all items of the Gengrid.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_del(Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if ((item->relcount > 0) || (item->walking > 0))
+     {
+        item->delete_me = EINA_TRUE;
+        elm_widget_item_pre_notify_del(item);
+        if (item->selected)
+          item->wd->selected = eina_list_remove(item->wd->selected, item);
+        if (item->gic->func.del)
+          item->gic->func.del((void *)item->base.data, item->wd->self);
+        return;
+     }
+
+   _item_del(item);
+}
+
+/**
+ * Set for what direction the Gengrid will expand.
+ *
+ * @param obj The Gengrid object.
+ * @param setting If @c EINA_TRUE the Gengrid will expand horizontally
+ * or vertically if @c EINA_FALSE.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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 items 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 Gengrid
+ *
+ * This clears all items in the Gengrid, leaving it empty.
+ *
+ * @param obj The Gengrid object.
+ *
+ * @see elm_gengrid_item_del() to remove just one item.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_clear(Evas_Object *obj)
+{
+   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;
+     }
+
+   if (wd->walking > 0)
+     {
+        Elm_Gengrid_Item *item;
+        wd->clear_me = 1;
+        EINA_INLIST_FOREACH(wd->items, item)
+        item->delete_me = 1;
+        return;
+     }
+   wd->clear_me = 0;
+   while (wd->items)
+     {
+        Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
+
+        wd->items = eina_inlist_remove(wd->items, wd->items);
+        elm_widget_item_pre_notify_del(item);
+        if (item->realized) _item_unrealize(item);
+        if (item->gic->func.del)
+          item->gic->func.del((void *)item->base.data, wd->self);
+        if (item->long_timer) ecore_timer_del(item->long_timer);
+        elm_widget_item_del(item);
+     }
+
+   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;
+   wd->count = 0;
+   evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
+   evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
+}
+
+/**
+ * Get the real evas object of the Gengrid item
+ *
+ * This returns the actual evas object used for the specified Gengrid
+ * item.  This may be NULL as it may not be created, and may be
+ * deleted at any time by Gengrid. Do not modify this object (move,
+ * resize, show, hide etc.) as Gengrid 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 item The Gengrid item.
+ * @return the evas object associated to this item.
+ *
+ * @see elm_gengrid_item_data_get()
+ *
+ * @ingroup Gengrid
+ */
+EAPI const Evas_Object *
+elm_gengrid_item_object_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->base.view;
+}
+
+/**
+ * Update the contents of an item
+ *
+ * This updates an item by calling all the item class functions again
+ * to get the icons, labels and states. Use this when the original
+ * item data has changed and the changes are desired to be reflected.
+ *
+ * @param item The item
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_update(Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (!item->realized) return;
+   if (item->want_unrealize) return;
+   _item_unrealize(item);
+   _item_realize(item);
+   _item_place(item, item->x, item->y);
+}
+
+/**
+ * Returns the data associated to a item
+ *
+ * This returns the data value passed on the elm_gengrid_item_append()
+ * and related item addition calls.
+ *
+ * @param item The Gengrid item.
+ * @return the data associated to this item.
+ *
+ * @see elm_gengrid_item_append()
+ * @see elm_gengrid_item_object_get()
+ *
+ * @ingroup Gengrid
+ */
+EAPI void *
+elm_gengrid_item_data_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_data_get(item);
+}
+
+/**
+ * Set the data item from the gengrid item
+ *
+ * This set the data value passed on the elm_gengrid_item_append() and
+ * related item addition calls. This function will also call
+ * elm_gengrid_item_update() so the item will be updated to reflect
+ * the new data.
+ *
+ * @param item The item
+ * @param data The new data pointer to set
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_data_set(Elm_Gengrid_Item *item,
+                          const void       *data)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_data_set(item, data);
+   elm_gengrid_item_update(item);
+}
+
+/**
+ * Get the item's coordinates.
+ *
+ * This returns the logical position of the item whithin the Gengrid.
+ *
+ * @param item The Gengrid item.
+ * @param x The x-axis coordinate pointer.
+ * @param y The y-axis coordinate pointer.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_pos_get(const Elm_Gengrid_Item *item,
+                         unsigned int           *x,
+                         unsigned int           *y)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (x) *x = item->x;
+   if (y) *y = item->y;
+}
+
+/**
+ * Enable or disable multi-select in the Gengrid.
+ *
+ * This enables (EINA_TRUE) or disables (EINA_FALSE) multi-select in
+ * the Gengrid.  This allows more than 1 item to be selected.
+ *
+ * @param obj The Gengrid object.
+ * @param multi Multi-select enabled/disabled
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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 Gengrid is enabled or disabled
+ *
+ * @param obj The Gengrid object
+ * @return Multi-select enable/disable
+ * (EINA_TRUE = enabled / EINA_FALSE = disabled)
+ *
+ * @ingroup Gengrid
+ */
+EAPI Eina_Bool
+elm_gengrid_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 item in the Gengrid
+ *
+ * This gets the selected item in the Gengrid (if multi-select is
+ * enabled only the first item in the list is selected - which is not
+ * very useful, so see elm_gengrid_selected_items_get() for when
+ * multi-select is used).
+ *
+ * If no item is selected, NULL is returned.
+ *
+ * @param obj The Gengrid object.
+ * @return The selected item, or NULL if none.
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_selected_item_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 items in the Gengrid.
+ *
+ * This returns a list of the selected items. This list pointer is
+ * only valid so long as no items are selected or unselected (or
+ * unselected implictly by deletion). The list contains
+ * Elm_Gengrid_Item pointers.
+ *
+ * @param obj The Gengrid object.
+ * @return The list of selected items, or NULL if none are selected.
+ *
+ * @ingroup Gengrid
+ */
+EAPI const Eina_List *
+elm_gengrid_selected_items_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;
+}
+
+/**
+ * Set the selected state of a item.
+ *
+ * This sets the selected state of a item. If multi-select is not
+ * enabled and selected is EINA_TRUE, previously selected items are
+ * unselected.
+ *
+ * @param item The item
+ * @param selected The selected state.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_selected_set(Elm_Gengrid_Item *item,
+                              Eina_Bool         selected)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   Widget_Data *wd = item->wd;
+   if (!wd) return;
+   if ((!item) || (item->delete_me)) return;
+   selected = !!selected;
+   if (item->selected == selected) return;
+
+   if (selected)
+     {
+        if (!wd->multi)
+          {
+             while (wd->selected)
+               _item_unselect(wd->selected->data);
+          }
+        _item_hilight(item);
+        _item_select(item);
+     }
+   else
+     _item_unselect(item);
+}
+
+/**
+ * Get the selected state of a item.
+ *
+ * This gets the selected state of a item (1 selected, 0 not selected).
+ *
+ * @param item The item
+ * @return The selected state
+ *
+ * @ingroup Gengrid
+ */
+EAPI Eina_Bool
+elm_gengrid_item_selected_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return item->selected;
+}
+
+/**
+ * Sets the disabled state of a item.
+ *
+ * A disabled item cannot be selected or unselected. It will also
+ * change appearance to disabled. This sets the disabled state (1
+ * disabled, 0 not disabled).
+ *
+ * @param item The item
+ * @param disabled The disabled state
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_disabled_set(Elm_Gengrid_Item *item,
+                              Eina_Bool         disabled)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (item->disabled == disabled) return;
+   if (item->delete_me) return;
+   item->disabled = disabled;
+   if (item->realized)
+     {
+        if (item->disabled)
+          edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
+        else
+          edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm");
+     }
+}
+
+/**
+ * Get the disabled state of a item.
+ *
+ * This gets the disabled state of the given item.
+ *
+ * @param item The item
+ * @return The disabled state
+ *
+ * @ingroup Gengrid
+ */
+EAPI Eina_Bool
+elm_gengrid_item_disabled_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   if (item->delete_me) return EINA_FALSE;
+   return item->disabled;
+}
+
+static Evas_Object *
+_elm_gengrid_item_label_create(void        *data,
+                               Evas_Object *obj,
+                               void *item   __UNUSED__)
+{
+   Evas_Object *label = elm_label_add(obj);
+   if (!label)
+     return NULL;
+   elm_object_style_set(label, "tooltip");
+   elm_label_label_set(label, data);
+   return label;
+}
+
+static void
+_elm_gengrid_item_label_del_cb(void            *data,
+                               Evas_Object *obj __UNUSED__,
+                               void *event_info __UNUSED__)
+{
+   eina_stringshare_del(data);
+}
+
+/**
+ * Set the text to be shown in the gengrid item.
+ *
+ * @param item Target item
+ * @param text The text to set in the content
+ *
+ * Setup the text as tooltip to object. The item can have only one
+ * tooltip, so any previous tooltip data is removed.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_tooltip_text_set(Elm_Gengrid_Item *item,
+                                  const char       *text)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   text = eina_stringshare_add(text);
+   elm_gengrid_item_tooltip_content_cb_set(item, _elm_gengrid_item_label_create,
+                                           text,
+                                           _elm_gengrid_item_label_del_cb);
+}
+
+/**
+ * Set the content to be shown in the tooltip item
+ *
+ * Setup the tooltip to item. The item can have only one tooltip, so
+ * any previous tooltip data is removed. @p func(with @p data) will be
+ * called every time that need show the tooltip and it should return a
+ * valid Evas_Object. This object is then managed fully by tooltip
+ * system and is deleted when the tooltip is gone.
+ *
+ * @param item the gengrid item being attached a tooltip.
+ * @param func the function used to create the tooltip contents.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_gengrid_item_tooltip_unset() or the owner @a item
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is the item.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_tooltip_content_cb_set(Elm_Gengrid_Item           *item,
+                                        Elm_Tooltip_Item_Content_Cb func,
+                                        const void                 *data,
+                                        Evas_Smart_Cb               del_cb)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(item, error);
+
+   if ((item->tooltip.content_cb == func) && (item->tooltip.data == data))
+     return;
+
+   if (item->tooltip.del_cb)
+     item->tooltip.del_cb((void *)item->tooltip.data,
+                          item->base.widget, item);
+   item->tooltip.content_cb = func;
+   item->tooltip.data = data;
+   item->tooltip.del_cb = del_cb;
+   if (item->base.view)
+     {
+        elm_widget_item_tooltip_content_cb_set(item,
+                                               item->tooltip.content_cb,
+                                               item->tooltip.data, NULL);
+        elm_widget_item_tooltip_style_set(item, item->tooltip.style);
+     }
+
+   return;
+
+error:
+   if (del_cb) del_cb((void *)data, NULL, NULL);
+}
+
+/**
+ * Unset tooltip from item
+ *
+ * @param item gengrid item to remove previously set tooltip.
+ *
+ * Remove tooltip from item. The callback provided as del_cb to
+ * elm_gengrid_item_tooltip_content_cb_set() will be called to notify
+ * it is not used anymore.
+ *
+ * @see elm_gengrid_item_tooltip_content_cb_set()
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_tooltip_unset(Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if ((item->base.view) && (item->tooltip.content_cb))
+     elm_widget_item_tooltip_unset(item);
+
+   if (item->tooltip.del_cb)
+     item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
+   item->tooltip.del_cb = NULL;
+   item->tooltip.content_cb = NULL;
+   item->tooltip.data = NULL;
+   if (item->tooltip.style)
+     elm_gengrid_item_tooltip_style_set(item, NULL);
+}
+
+/**
+ * Sets a different style for this item tooltip.
+ *
+ * @note before you set a style you should define a tooltip with
+ *       elm_gengrid_item_tooltip_content_cb_set() or
+ *       elm_gengrid_item_tooltip_text_set()
+ *
+ * @param item gengrid item with tooltip already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_tooltip_style_set(Elm_Gengrid_Item *item,
+                                   const char       *style)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   eina_stringshare_replace(&item->tooltip.style, style);
+   if (item->base.view) elm_widget_item_tooltip_style_set(item, style);
+}
+
+/**
+ * Get the style for this item tooltip.
+ *
+ * @param item gengrid item with tooltip already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a tooltip set, then NULL is returned.
+ *
+ * @ingroup Gengrid
+ */
+EAPI const char *
+elm_gengrid_item_tooltip_style_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->tooltip.style;
+}
+
+/**
+ * Set the cursor to be shown when mouse is over the gengrid item
+ *
+ * @param item Target item
+ * @param cursor the cursor name to be used.
+ *
+ * @see elm_object_cursor_set()
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_cursor_set(Elm_Gengrid_Item *item,
+                            const char       *cursor)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   eina_stringshare_replace(&item->mouse_cursor, cursor);
+   if (item->base.view) elm_widget_item_cursor_set(item, cursor);
+}
+
+/**
+ * Get the cursor to be shown when mouse is over the gengrid item
+ *
+ * @param item gengrid item with cursor already set.
+ * @return the cursor name.
+ *
+ * @ingroup Gengrid
+ */
+EAPI const char *
+elm_gengrid_item_cursor_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_get(item);
+}
+
+/**
+ * Unset the cursor to be shown when mouse is over the gengrid item
+ *
+ * @param item Target item
+ *
+ * @see elm_object_cursor_unset()
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_cursor_unset(Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (!item->mouse_cursor)
+     return;
+
+   if (item->base.view)
+     elm_widget_item_cursor_unset(item);
+
+   eina_stringshare_del(item->mouse_cursor);
+   item->mouse_cursor = NULL;
+}
+
+/**
+ * Sets a different style for this item cursor.
+ *
+ * @note before you set a style you should define a cursor with
+ *       elm_gengrid_item_cursor_set()
+ *
+ * @param item gengrid item with cursor already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_cursor_style_set(Elm_Gengrid_Item *item,
+                                  const char       *style)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_style_set(item, style);
+}
+
+/**
+ * Get the style for this item cursor.
+ *
+ * @param item gengrid item with cursor already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup Gengrid
+ */
+EAPI const char *
+elm_gengrid_item_cursor_style_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_style_get(item);
+}
+
+/**
+ * Set if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a
+ * cursor with elm_object_cursor_set(). By default it will only look
+ * for cursors provided by the engine.
+ *
+ * @param item widget item with cursor already set.
+ * @param engine_only boolean to define it cursors should be looked
+ * only between the provided by the engine or searched on widget's
+ * theme as well.
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_cursor_engine_only_set(Elm_Gengrid_Item *item,
+                                        Eina_Bool         engine_only)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_engine_only_set(item, engine_only);
+}
+
+/**
+ * Get the cursor engine only usage for this item cursor.
+ *
+ * @param item widget item with cursor already set.
+ * @return engine_only boolean to define it cursors should be looked
+ * only between the provided by the engine or searched on widget's
+ * theme as well. If the object does not have a cursor set, then
+ * EINA_FALSE is returned.
+ *
+ * @ingroup Gengrid
+ */
+EAPI Eina_Bool
+elm_gengrid_item_cursor_engine_only_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return elm_widget_item_cursor_engine_only_get(item);
+}
+
+/**
+ * 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_gengrid_always_select_mode_set(). This means even if selected,
+ * every click will make the selected callbacks be called.
+ *
+ * @param obj The Gengrid object
+ * @param always_select The always select mode (EINA_TRUE = on,
+ * EINA_FALSE = off)
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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 Gengrid object.
+ * @return The always select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Gengrid
+ */
+EAPI Eina_Bool
+elm_gengrid_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 Gengrid object
+ * @param no_select The no select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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 Gengrid object
+ * @return The no select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Gengrid
+ */
+EAPI Eina_Bool
+elm_gengrid_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
+ * Gengrid. See elm_scroller_bounce_set() for details.
+ *
+ * @param obj The Gengrid object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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 Gengrid object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_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);
+}
+
+/**
+ * Get all items in the Gengrid.
+ *
+ * This returns a list of the Gengrid items. The list contains
+ * Elm_Gengrid_Item pointers.
+ *
+ * @param obj The Gengrid object.
+ * @return The list of items, or NULL if none.
+ *
+ * @ingroup Gengrid
+ */
+
+/**
+ * Set gengrid scroll page size relative to viewport size.
+ *
+ * The gengrid scroller is capable 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 content 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_gengrid_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 gengrid object
+ * @param h_pagerel The horizontal page relative size
+ * @param v_pagerel The vertical page relative size
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_page_relative_set(Evas_Object *obj,
+                              double       h_pagerel,
+                              double       v_pagerel)
+{
+   Evas_Coord pagesize_h;
+   Evas_Coord pagesize_v;
+
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
+   elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
+                                 pagesize_v);
+}
+
+/**
+ * Set gengrid scroll page size.
+ *
+ * See also elm_gengrid_page_relative_set(). This, instead of a page
+ * size being relative to the viewport, sets it to an absolute fixed
+ * value, with 0 turning it off for that axis.
+ *
+ * @param obj The gengrid object
+ * @param h_pagesize The horizontal page size
+ * @param v_pagesize The vertical page size
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_page_size_set(Evas_Object *obj,
+                          Evas_Coord   h_pagesize,
+                          Evas_Coord   v_pagesize)
+{
+   double pagerel_h;
+   double pagerel_v;
+
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
+   elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
+                                 v_pagesize);
+}
+
+/**
+ * Get the first item in the gengrid
+ *
+ * This returns the first item in the list.
+ *
+ * @param obj The gengrid object
+ * @return The first item, or NULL if none
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_first_item_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->items) return NULL;
+   Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
+   while ((item) && (item->delete_me))
+     item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
+   return item;
+}
+
+/**
+ * Get the last item in the gengrid
+ *
+ * This returns the last item in the list.
+ *
+ * @return The last item, or NULL if none
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_last_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd->items) return NULL;
+   Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
+   if (!wd) return NULL;
+   while ((item) && (item->delete_me))
+     item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
+   return item;
+}
+
+/**
+ * Get the next item in the gengrid
+ *
+ * This returns the item after the item @p item.
+ *
+ * @param item The item
+ * @return The item after @p item, or NULL if none
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_item_next_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   while (item)
+     {
+        item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
+        if ((item) && (!item->delete_me)) break;
+     }
+   return (Elm_Gengrid_Item *)item;
+}
+
+/**
+ * Get the previous item in the gengrid
+ *
+ * This returns the item before the item @p item.
+ *
+ * @param item The item
+ * @return The item before @p item, or NULL if none
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Gengrid_Item *
+elm_gengrid_item_prev_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   while (item)
+     {
+        item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
+        if ((item) && (!item->delete_me)) break;
+     }
+   return (Elm_Gengrid_Item *)item;
+}
+
+/**
+ * Get the gengrid object from an item
+ *
+ * This returns the gengrid object itself that an item belongs to.
+ *
+ * @param item The item
+ * @return The gengrid object
+ *
+ * @ingroup Gengrid
+ */
+EAPI Evas_Object *
+elm_gengrid_item_gengrid_get(const Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->base.widget;
+}
+
+/**
+ * Show the given item
+ *
+ * This causes gengrid to jump to the given item @p item and show it
+ * (by scrolling), if it is not fully visible.
+ *
+ * @param item The item
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_show(Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   Widget_Data *wd = elm_widget_data_get(item->wd->self);
+   Evas_Coord minx = 0, miny = 0;
+
+   if (!wd) return;
+   if ((!item) || (item->delete_me)) return;
+   _pan_min_get(wd->pan_smart, &minx, &miny);
+
+   elm_smart_scroller_child_region_show(item->wd->scr,
+                                        item->x * wd->item_width + minx,
+                                        item->y * wd->item_height + miny,
+                                        item->wd->item_width,
+                                        item->wd->item_height);
+}
+
+/**
+ * Bring in the given item
+ *
+ * This causes gengrig to jump to the given item @p item and show it
+ * (by scrolling), if it is not fully visible. This may use animation
+ * to do so and take a period of time
+ *
+ * @param item The item
+ *
+ * @ingroup Gengrid
+ */
+EAPI void
+elm_gengrid_item_bring_in(Elm_Gengrid_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (item->delete_me) return;
+
+   Evas_Coord minx = 0, miny = 0;
+   Widget_Data *wd = elm_widget_data_get(item->wd->self);
+   if (!wd) return;
+   _pan_min_get(wd->pan_smart, &minx, &miny);
+
+   elm_smart_scroller_region_bring_in(item->wd->scr,
+                                      item->x * wd->item_width + minx,
+                                      item->y * wd->item_height + miny,
+                                      item->wd->item_width,
+                                      item->wd->item_height);
+}
diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c
new file mode 100644 (file)
index 0000000..b162574
--- /dev/null
@@ -0,0 +1,4873 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#include "elm_priv.h"
+
+#define SWIPE_MOVES         12
+#define MAX_ITEMS_PER_BLOCK 32
+#define LONGPRESS_TIMEOUT   1.0
+
+/**
+ * @defgroup Genlist Genlist
+ *
+ * The aim was to have more expansive list than the simple list in
+ * Elementary that could have more flexible items and allow many more entries
+ * while still being fast and low on memory usage. At the same time it was
+ * also made to be able to do tree structures. But the price to pay is more
+ * complex when it comes to usage. If all you want is a simple list with
+ * icons and a single label, use the normal List object.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * clicked - This is called when a user has double-clicked an item. The
+ * event_info parameter is the genlist item that was double-clicked.
+ *
+ * selected - This is called when a user has made an item selected. The
+ * event_info parameter is the genlist item that was selected.
+ *
+ * unselected - This is called when a user has made an item unselected. The
+ * event_info parameter is the genlist item that was unselected.
+ *
+ * expanded - This is called when elm_genlist_item_expanded_set() is called
+ * and the item is now meant to be expanded. The event_info parameter is the
+ * genlist item that was indicated to expand. It is the job of this callback
+ * to then fill in the child items.
+ *
+ * contracted - This is called when elm_genlist_item_expanded_set() is called
+ * and the item is now meant to be contracted. The event_info parameter is
+ * the genlist item that was indicated to contract. It is the job of this
+ * callback to then delete the child items.
+ *
+ * expand,request - This is called when a user has indicated they want to
+ * expand a tree branch item. The callback should decide if the item can
+ * expand (has any children) and then call elm_genlist_item_expanded_set()
+ * appropriately to set the state. The event_info parameter is the genlist
+ * item that was indicated to expand.
+ *
+ * contract,request - This is called when a user has indicated they want to
+ * contract a tree branch item. The callback should decide if the item can
+ * contract (has any children) and then call elm_genlist_item_expanded_set()
+ * appropriately to set the state. The event_info parameter is the genlist
+ * item that was indicated to contract.
+ *
+ * realized - This is called when the item in the list is created as a real
+ * evas object. event_info parameter is the genlist item 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_genlist_item_object_get() in a way
+ * where it may point to freed objects.
+ *
+ * unrealized - This is called just before an item is unrealized. After
+ * this call icon objects provided will be deleted and the item object
+ * itself delete or be put into a floating cache.
+ *
+ * drag,start,up - This is called when the item in the list has been dragged
+ * (not scrolled) up.
+ *
+ * drag,start,down - This is called when the item in the list has been dragged
+ * (not scrolled) down.
+ *
+ * drag,start,left - This is called when the item in the list has been dragged
+ * (not scrolled) left.
+ *
+ * drag,start,right - This is called when the item in the list has been dragged
+ * (not scrolled) right.
+ *
+ * drag,stop - This is called when the item in the list has stopped being
+ * dragged.
+ *
+ * drag - This is called when the item in the list is being dragged.
+ *
+ * longpressed - This is called when the item is pressed for a certain amount
+ * of time. By default it's 1 second.
+ *
+ * scroll,edge,top - This is called when the genlist is scrolled until the top
+ * edge.
+ *
+ * scroll,edge,bottom - This is called when the genlist is scrolled until the
+ * bottom edge.
+ *
+ * scroll,edge,left - This is called when the genlist is scrolled until the
+ * left edge.
+ *
+ * scroll,edge,right - This is called when the genlist is scrolled until the
+ * right edge.
+ *
+ * multi,swipe,left - This is called when the genlist is multi-touch swiped
+ * left.
+ *
+ * multi,swipe,right - This is called when the genlist is multi-touch swiped
+ * right.
+ *
+ * multi,swipe,up - This is called when the genlist is multi-touch swiped
+ * up.
+ *
+ * multi,swipe,down - This is called when the genlist is multi-touch swiped
+ * down.
+ *
+ * multi,pinch,out - This is called when the genlist is multi-touch pinched
+ * out.
+ *
+ * multi,pinch,in - This is called when the genlist is multi-touch pinched
+ * in.
+ *
+ * Genlist has a fairly large API, mostly because it's relatively complex,
+ * trying to be both expansive, powerful and efficient. First we will begin
+ * an overview on the theory behind genlist.
+ *
+ * Evas tracks every object you create. Every time it processes an event
+ * (mouse move, down, up etc.) it needs to walk through objects and find out
+ * what event that affects. Even worse every time it renders display updates,
+ * in order to just calculate what to re-draw, it needs to walk through many
+ * many many objects. Thus, the more objects you keep active, the more
+ * overhead Evas has in just doing its work. It is advisable to keep your
+ * active objects to the minimum working set you need. Also remember that
+ * object creation and deletion carries an overhead, so there is a
+ * middle-ground, which is not easily determined. But don't keep massive lists
+ * of objects you can't see or use. Genlist does this with list objects. It
+ * creates and destroys them dynamically as you scroll around. It groups them
+ * into blocks so it can determine the visibility etc. of a whole block at
+ * once as opposed to having to walk the whole list. This 2-level list allows
+ * for very large numbers of items to be in the list (tests have used up to
+ * 2,000,000 items). Also genlist employs a queue for adding items. As items
+ * may be different sizes, every item added needs to be calculated as to its
+ * size and thus this presents a lot of overhead on populating the list, this
+ * genlist employs a queue. Any item added is queued and spooled off over
+ * time, actually appearing some time later, so if your list has many members
+ * you may find it takes a while for them to all appear, with your process
+ * consuming a lot of CPU while it is busy spooling.
+ *
+ * Genlist also implements a tree structure, but it does so with callbacks to
+ * the application, with the application filling in tree structures when
+ * requested (allowing for efficient building of a very deep tree that could
+ * even be used for file-management). See the above smart signal callbacks for
+ * details.
+ *
+ * An item in the genlist world 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 genlist item) and
+ * 0 or more boolean states that can be used for check, radio or other
+ * indicators by the edje theme style. An item may be one of several styles
+ * (Elementary provides 4 by default - “default”, “double_label”, "group_index"
+ * and "icon_top_text_bottom", but this can be extended by system or
+ * application custom themes/overlays/extensions).
+ *
+ * In order to implement the ability to add and delete items on the fly,
+ * Genlist implements a class/callback system where the application provides
+ * a structure with information about that type of item (genlist may contain
+ * multiple different items with different classes, states and styles).
+ * Genlist will call the functions in this struct (methods) when an item 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:
+ *
+ * item_style - This is a constant string and simply defines the name of the
+ * item style. It must be specified and the default should be “default”.
+ *
+ * func.label_get - This function is called when an actual item object is
+ * created. The data parameter is the data parameter passed to
+ * elm_genlist_item_append() and related item creation functions. The obj
+ * parameter is the genlist 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 strudup()'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 data parameter passed to
+ * elm_genlist_item_append() and related item creation functions. The obj
+ * parameter is the genlist 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 genlist on shutdown or when the item
+ * is unrealized.
+ *
+ * func.state_get - This function is called when an actual item object is
+ * created. The data parameter is the data parameter passed to
+ * elm_genlist_item_append() and related item creation functions. The obj
+ * parameter is the genlist object and the part parameter is the string name
+ * of the state part in the edje design that is listed as one of the possible
+ * states that can be set. Return 0 for false or 1 for true. Genlist 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_genlist_item_del() is called on an
+ * item, elm_genlist_clear() is called on the genlist, or
+ * elm_genlist_item_subitems_clear() is called to clear sub-items. This is
+ * intended for use when actual genlist items are deleted, so any backing
+ * data attached to the item (e.g. its data parameter on creation) can be
+ * deleted.
+ *
+ * Items can be added by several calls. All of them return a Elm_Genlist_Item
+ * handle that is an internal member inside the genlist. They all take a data
+ * parameter that is meant to be used for a handle to the applications
+ * internal data (eg the struct with the original item data). The parent
+ * parameter is the parent genlist item this belongs to if it is a tree or 
+ * an indexed group, and NULL if there is no parent. The flags can be a bitmask
+ * of ELM_GENLIST_ITEM_NONE, ELM_GENLIST_ITEM_SUBITEMS and
+ * ELM_GENLIST_ITEM_GROUP. If ELM_GENLIST_ITEM_SUBITEMS is set then this item
+ * is displayed as an item that is able to expand and have child items.
+ * If ELM_GENLIST_ITEM_GROUP is set then this item is group idex item that is
+ * displayed at the top until the next group comes. The func parameter is a
+ * convenience callback that is called when the item is selected and the data
+ * parameter will be the func_data parameter, obj be the genlist object and
+ * event_info will be the genlist item.
+ *
+ * elm_genlist_item_append() appends an item to the end of the list, or if
+ * there is a parent, to the end of all the child items of the parent.
+ * elm_genlist_item_prepend() is the same but prepends to the beginning of
+ * the list or children list. elm_genlist_item_insert_before() inserts at
+ * item before another item and elm_genlist_item_insert_after() inserts after
+ * the indicated item.
+ *
+ * The application can clear the list with elm_genlist_clear() which deletes
+ * all the items in the list and elm_genlist_item_del() will delete a specific
+ * item. elm_genlist_item_subitems_clear() will clear all items that are
+ * children of the indicated parent item.
+ *
+ * If the application wants multiple items to be able to be selected,
+ * elm_genlist_multi_select_set() can enable this. If the list is
+ * single-selection only (the default), then elm_genlist_selected_item_get()
+ * will return the selected item, if any, or NULL I none is selected. If the
+ * list is multi-select then elm_genlist_selected_items_get() will return a
+ * list (that is only valid as long as no items are modified (added, deleted,
+ * selected or unselected)).
+ *
+ * To help inspect list items you can jump to the item at the top of the list
+ * with elm_genlist_first_item_get() which will return the item pointer, and
+ * similarly elm_genlist_last_item_get() gets the item at the end of the list.
+ * elm_genlist_item_next_get() and elm_genlist_item_prev_get() get the next
+ * and previous items respectively relative to the indicated item. Using
+ * these calls you can walk the entire item list/tree. Note that as a tree
+ * the items are flattened in the list, so elm_genlist_item_parent_get() will
+ * let you know which item is the parent (and thus know how to skip them if
+ * wanted).
+ *
+ * There are also convenience functions. elm_genlist_item_genlist_get() will
+ * return the genlist object the item belongs to. elm_genlist_item_show()
+ * will make the scroller scroll to show that specific item so its visible.
+ * elm_genlist_item_data_get() returns the data pointer set by the item
+ * creation functions.
+ *
+ * If an item changes (state of boolean changes, label or icons change),
+ * then use elm_genlist_item_update() to have genlist update the item with
+ * the new state. Genlist will re-realize the item thus call the functions
+ * in the _Elm_Genlist_Item_Class for that item.
+ *
+ * To programmatically (un)select an item use elm_genlist_item_selected_set().
+ * To get its selected state use elm_genlist_item_selected_get(). Similarly
+ * to expand/contract an item and get its expanded state, use
+ * elm_genlist_item_expanded_set() and elm_genlist_item_expanded_get(). And
+ * again to make an item disabled (unable to be selected and appear
+ * differently) use elm_genlist_item_disabled_set() to set this and
+ * elm_genlist_item_disabled_get() to get the disabled state.
+ *
+ * In general to indicate how the genlist should expand items horizontally to
+ * fill the list area, use elm_genlist_horizontal_mode_set(). Valid modes are
+ * ELM_LIST_LIMIT and ELM_LIST_SCROLL . The default is ELM_LIST_SCROLL. This
+ * mode means that if items are too wide to fit, the scroller will scroll
+ * horizontally. Otherwise items are expanded to fill the width of the
+ * viewport of the scroller. If it is ELM_LIST_LIMIT, items will be expanded
+ * to the viewport width and limited to that size. This can be combined with
+ * a different style that uses edjes' ellipsis feature (cutting text off like
+ * this: “tex...”).
+ *
+ * Items 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_genlist_always_select_mode_set(). This means even if
+ * selected, every click will make the selected callbacks be called.
+ * elm_genlist_no_select_mode_set() will turn off the ability to select
+ * items entirely and they will neither appear selected nor call selected
+ * callback functions.
+ *
+ * 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.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Item_Block  Item_Block;
+typedef struct _Pan         Pan;
+typedef struct _Item_Cache  Item_Cache;
+
+struct _Widget_Data
+{
+   Evas_Object      *obj, *scr, *pan_smart;
+   Eina_Inlist      *items, *blocks;
+   Eina_List        *group_items;
+   Pan              *pan;
+   Evas_Coord        pan_x, pan_y, w, h, minw, minh, realminw, prev_viewport_w;
+   Ecore_Job        *calc_job, *update_job;
+   Ecore_Idler      *queue_idler;
+   Ecore_Idler      *must_recalc_idler;
+   Eina_List        *queue, *selected;
+   Elm_Genlist_Item *show_item;
+   Elm_Genlist_Item *last_selected_item;
+   Eina_Inlist      *item_cache;
+   Elm_Genlist_Item *anchor_item;
+   Evas_Coord        anchor_y;
+   Elm_List_Mode     mode;
+   Ecore_Timer      *multi_timer;
+   Evas_Coord        prev_x, prev_y, prev_mx, prev_my;
+   Evas_Coord        cur_x, cur_y, cur_mx, cur_my;
+   Eina_Bool         mouse_down : 1;
+   Eina_Bool         multi_down : 1;
+   Eina_Bool         multi_timeout : 1;
+   Eina_Bool         multitouched : 1;
+   Eina_Bool         on_hold : 1;
+   Eina_Bool         multi : 1;
+   Eina_Bool         always_select : 1;
+   Eina_Bool         longpressed : 1;
+   Eina_Bool         wasselected : 1;
+   Eina_Bool         no_select : 1;
+   Eina_Bool         bring_in : 1;
+   Eina_Bool         compress : 1;
+   Eina_Bool         height_for_width : 1;
+   Eina_Bool         homogeneous : 1;
+   Eina_Bool         clear_me : 1;
+   Eina_Bool         swipe : 1;
+   struct
+   {
+      Evas_Coord x, y;
+   } history[SWIPE_MOVES];
+   int               multi_device;
+   int               item_cache_count;
+   int               item_cache_max;
+   int               movements;
+   int               walking;
+   int               item_width;
+   int               item_height;
+   int               max_items_per_block;
+   double            longpress_timeout;
+};
+
+struct _Item_Block
+{
+   EINA_INLIST;
+   int          count;
+   int          num;
+   Widget_Data *wd;
+   Eina_List   *items;
+   Evas_Coord   x, y, w, h, minw, minh;
+   Eina_Bool    want_unrealize : 1;
+   Eina_Bool    realized : 1;
+   Eina_Bool    changed : 1;
+   Eina_Bool    updateme : 1;
+   Eina_Bool    showme : 1;
+   Eina_Bool    must_recalc : 1;
+};
+
+struct _Elm_Genlist_Item
+{
+   Elm_Widget_Item               base;
+   EINA_INLIST;
+   Widget_Data                  *wd;
+   Item_Block                   *block;
+   Eina_List                    *items;
+   Evas_Coord                    x, y, w, h, minw, minh;
+   const Elm_Genlist_Item_Class *itc;
+   Elm_Genlist_Item             *parent;
+   Elm_Genlist_Item             *group_item;
+   Elm_Genlist_Item_Flags        flags;
+   struct
+   {
+      Evas_Smart_Cb func;
+      const void   *data;
+   } func;
+
+   Evas_Object      *spacer;
+   Eina_List        *labels, *icons, *states, *icon_objs;
+   Ecore_Timer      *long_timer;
+   Ecore_Timer      *swipe_timer;
+   Evas_Coord        dx, dy;
+   Evas_Coord        scrl_x, scrl_y;
+
+   Elm_Genlist_Item *rel;
+
+   struct
+   {
+      const void                 *data;
+      Elm_Tooltip_Item_Content_Cb content_cb;
+      Evas_Smart_Cb               del_cb;
+      const char                 *style;
+   } tooltip;
+
+   const char *mouse_cursor;
+
+   int         relcount;
+   int         walking;
+   int         expanded_depth;
+   int         order_num_in;
+
+   Eina_Bool   before : 1;
+
+   Eina_Bool   want_unrealize : 1;
+   Eina_Bool   want_realize : 1;
+   Eina_Bool   realized : 1;
+   Eina_Bool   selected : 1;
+   Eina_Bool   hilighted : 1;
+   Eina_Bool   expanded : 1;
+   Eina_Bool   disabled : 1;
+   Eina_Bool   display_only : 1;
+   Eina_Bool   mincalcd : 1;
+   Eina_Bool   queued : 1;
+   Eina_Bool   showme : 1;
+   Eina_Bool   delete_me : 1;
+   Eina_Bool   down : 1;
+   Eina_Bool   dragging : 1;
+   Eina_Bool   updateme : 1;
+};
+
+struct _Item_Cache
+{
+   EINA_INLIST;
+
+   Evas_Object *base_view, *spacer;
+
+   const char  *item_style; // it->itc->item_style
+   Eina_Bool    tree : 1; // it->flags & ELM_GENLIST_ITEM_SUBITEMS
+   Eina_Bool    compress : 1; // it->wd->compress
+   Eina_Bool    odd : 1; // in & 0x1
+
+   Eina_Bool    selected : 1; // it->selected
+   Eina_Bool    disabled : 1; // it->disabled
+   Eina_Bool    expanded : 1; // it->expanded
+};
+
+#define ELM_GENLIST_ITEM_FROM_INLIST(item) \
+  ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Genlist_Item) : NULL)
+
+struct _Pan
+{
+   Evas_Object_Smart_Clipped_Data __clipped_data;
+   Widget_Data                   *wd;
+   Ecore_Job                     *resize_job;
+};
+
+static const char *widtype = NULL;
+static void      _item_cache_zero(Widget_Data *wd);
+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      _item_unrealize(Elm_Genlist_Item *it);
+static void      _item_block_unrealize(Item_Block *itb);
+static void      _calc_job(void *data);
+static void      _on_focus_hook(void        *data,
+                                Evas_Object *obj);
+static Eina_Bool _item_multi_select_up(Widget_Data *wd);
+static Eina_Bool _item_multi_select_down(Widget_Data *wd);
+static Eina_Bool _item_single_select_up(Widget_Data *wd);
+static Eina_Bool _item_single_select_down(Widget_Data *wd);
+static Eina_Bool _event_hook(Evas_Object       *obj,
+                             Evas_Object       *src,
+                             Evas_Callback_Type type,
+                             void              *event_info);
+static Eina_Bool _deselect_all_items(Widget_Data *wd);
+static void      _pan_calculate(Evas_Object *obj);
+
+static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
+
+static Eina_Bool
+_event_hook(Evas_Object       *obj,
+            Evas_Object *src   __UNUSED__,
+            Evas_Callback_Type type,
+            void              *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (!wd->items) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   Elm_Genlist_Item *it = NULL;
+   Evas_Coord x = 0;
+   Evas_Coord y = 0;
+   Evas_Coord step_x = 0;
+   Evas_Coord step_y = 0;
+   Evas_Coord v_w = 0;
+   Evas_Coord v_h = 0;
+   Evas_Coord page_x = 0;
+   Evas_Coord page_y = 0;
+
+   elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
+   elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
+   elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
+
+   if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
+     {
+        x -= step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Right")) ||
+            (!strcmp(ev->keyname, "KP_Right")))
+     {
+        x += step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
+     {
+        if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+             (_item_multi_select_up(wd)))
+            || (_item_single_select_up(wd)))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          y -= step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
+     {
+        if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+             (_item_multi_select_down(wd)))
+            || (_item_single_select_down(wd)))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          y += step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Home")) ||
+            (!strcmp(ev->keyname, "KP_Home")))
+     {
+        it = elm_genlist_first_item_get(obj);
+        elm_genlist_item_bring_in(it);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "End")) ||
+            (!strcmp(ev->keyname, "KP_End")))
+     {
+        it = elm_genlist_last_item_get(obj);
+        elm_genlist_item_bring_in(it);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "Prior")) ||
+            (!strcmp(ev->keyname, "KP_Prior")))
+     {
+        if (page_y < 0)
+          y -= -(page_y * v_h) / 100;
+        else
+          y -= page_y;
+     }
+   else if ((!strcmp(ev->keyname, "Next")) ||
+            (!strcmp(ev->keyname, "KP_Next")))
+     {
+        if (page_y < 0)
+          y += -(page_y * v_h) / 100;
+        else
+          y += page_y;
+     }
+   else if(((!strcmp(ev->keyname, "Return")) ||
+            (!strcmp(ev->keyname, "KP_Enter")) ||
+            (!strcmp(ev->keyname, "space")))
+           && (!wd->multi) && (wd->selected))
+     {
+        Elm_Genlist_Item *it = elm_genlist_selected_item_get(obj);
+        elm_genlist_item_expanded_set(it,
+                                      !elm_genlist_item_expanded_get(it));
+     }
+   else if (!strcmp(ev->keyname, "Escape"))
+     {
+        if (!_deselect_all_items(wd)) return EINA_FALSE;
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else return EINA_FALSE;
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   elm_smart_scroller_child_pos_set(wd->scr, x, y);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_deselect_all_items(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   while(wd->selected)
+     elm_genlist_item_selected_set(wd->selected->data, EINA_FALSE);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_up(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   if (!wd->multi) return EINA_FALSE;
+
+   Elm_Genlist_Item *prev = elm_genlist_item_prev_get(wd->last_selected_item);
+   if (!prev) return EINA_TRUE;
+
+   if (elm_genlist_item_selected_get(prev))
+     {
+        elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = prev;
+        elm_genlist_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_genlist_item_selected_set(prev, EINA_TRUE);
+        elm_genlist_item_show(prev);
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_down(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   if (!wd->multi) return EINA_FALSE;
+
+   Elm_Genlist_Item *next = elm_genlist_item_next_get(wd->last_selected_item);
+   if (!next) return EINA_TRUE;
+
+   if (elm_genlist_item_selected_get(next))
+     {
+        elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = next;
+        elm_genlist_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_genlist_item_selected_set(next, EINA_TRUE);
+        elm_genlist_item_show(next);
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_up(Widget_Data *wd)
+{
+   Elm_Genlist_Item *prev;
+   if (!wd->selected)
+     {
+        prev = ELM_GENLIST_ITEM_FROM_INLIST(wd->items->last);
+        while ((prev) && (prev->delete_me))
+          prev = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
+     }
+   else prev = elm_genlist_item_prev_get(wd->last_selected_item);
+
+   if (!prev) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_genlist_item_selected_set(prev, EINA_TRUE);
+   elm_genlist_item_show(prev);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_down(Widget_Data *wd)
+{
+   Elm_Genlist_Item *next;
+   if (!wd->selected)
+     {
+        next = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
+        while ((next) && (next->delete_me))
+          next = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
+     }
+   else next = elm_genlist_item_next_get(wd->last_selected_item);
+
+   if (!next) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_genlist_item_selected_set(next, EINA_TRUE);
+   elm_genlist_item_show(next);
+   return EINA_TRUE;
+}
+
+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))
+     {
+        edje_object_signal_emit(wd->obj, "elm,action,focus", "elm");
+        evas_object_focus_set(wd->obj, EINA_TRUE);
+        if ((wd->selected) && (!wd->last_selected_item))
+          wd->last_selected_item = eina_list_data_get(wd->selected);
+     }
+   else
+     {
+        edje_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
+        evas_object_focus_set(wd->obj, EINA_FALSE);
+     }
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _item_cache_zero(wd);
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   if (wd->update_job) ecore_job_del(wd->update_job);
+   if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
+   if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
+   free(wd);
+}
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_del(wd->pan_smart);
+   wd->pan_smart = NULL;
+   elm_genlist_clear(obj);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Item_Block *itb;
+   if (!wd) return;
+   _item_cache_zero(wd);
+   elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
+                                       elm_widget_style_get(obj));
+//   edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
+   wd->item_width = wd->item_height = 0;
+   wd->minw = wd->minh = wd->realminw = 0;
+   EINA_INLIST_FOREACH(wd->blocks, itb)
+   {
+      Eina_List *l;
+      Elm_Genlist_Item *it;
+
+      if (itb->realized) _item_block_unrealize(itb);
+      EINA_LIST_FOREACH(itb->items, l, it)
+        it->mincalcd = EINA_FALSE;
+
+      itb->changed = EINA_TRUE;
+   }
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   _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);
+   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 minw = -1, minh = -1, maxw = -1, maxh = -1;
+   if (!wd) return;
+   evas_object_size_hint_min_get(wd->scr, &minw, &minh);
+   evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
+   minh = -1;
+   if (wd->height_for_width)
+     {
+        Evas_Coord vw, vh;
+
+        elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
+        if ((vw != 0) && (vw != wd->prev_viewport_w))
+          {
+             Item_Block *itb;
+
+             wd->prev_viewport_w = vw;
+             EINA_INLIST_FOREACH(wd->blocks, itb)
+             {
+                itb->must_recalc = EINA_TRUE;
+             }
+             if (wd->calc_job) ecore_job_del(wd->calc_job);
+             wd->calc_job = ecore_job_add(_calc_job, wd);
+          }
+     }
+   if (wd->mode == ELM_LIST_LIMIT)
+     {
+        Evas_Coord vmw, vmh, vw, vh;
+
+        minw = wd->realminw;
+        maxw = -1;
+        elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
+        if ((minw > 0) && (vw < minw)) vw = minw;
+        else if ((maxw > 0) && (vw > maxw))
+          vw = maxw;
+        edje_object_size_min_calc
+          (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
+        minw = vmw + minw;
+     }
+   else
+     {
+        Evas_Coord vmw, vmh;
+
+        edje_object_size_min_calc
+          (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
+        minw = vmw;
+        minh = vmh;
+     }
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_item_hilight(Elm_Genlist_Item *it)
+{
+   const char *selectraise;
+   if ((it->wd->no_select) || (it->delete_me) || (it->hilighted)) return;
+   edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
+   selectraise = edje_object_data_get(it->base.view, "selectraise");
+   if ((selectraise) && (!strcmp(selectraise, "on")))
+     {
+        evas_object_raise(it->base.view);
+        if ((it->group_item) && (it->group_item->realized))
+           evas_object_raise(it->group_item->base.view);
+     }
+   it->hilighted = EINA_TRUE;
+}
+
+static void
+_item_block_del(Elm_Genlist_Item *it)
+{
+   Eina_Inlist *il;
+   Item_Block *itb = it->block;
+
+   itb->items = eina_list_remove(itb->items, it);
+   itb->count--;
+   itb->changed = EINA_TRUE;
+   if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
+   it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
+   if (itb->count < 1)
+     {
+        il = EINA_INLIST_GET(itb);
+        Item_Block *itbn = (Item_Block *)(il->next);
+        if (it->parent)
+          it->parent->items = eina_list_remove(it->parent->items, it);
+        else
+          it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
+        free(itb);
+        if (itbn) itbn->changed = EINA_TRUE;
+     }
+   else
+     {
+        if (itb->count < 16)
+          {
+             il = EINA_INLIST_GET(itb);
+             Item_Block *itbp = (Item_Block *)(il->prev);
+             Item_Block *itbn = (Item_Block *)(il->next);
+             if ((itbp) && ((itbp->count + itb->count) < 48))
+               {
+                  Elm_Genlist_Item *it2;
+
+                  EINA_LIST_FREE(itb->items, it2)
+                    {
+                       it2->block = itbp;
+                       itbp->items = eina_list_append(itbp->items, it2);
+                       itbp->count++;
+                       itbp->changed = EINA_TRUE;
+                    }
+                  it->wd->blocks = eina_inlist_remove(it->wd->blocks,
+                                                      EINA_INLIST_GET(itb));
+                  free(itb);
+               }
+             else if ((itbn) && ((itbn->count + itb->count) < 48))
+               {
+                  while (itb->items)
+                    {
+                       Eina_List *last = eina_list_last(itb->items);
+                       Elm_Genlist_Item *it2 = last->data;
+
+                       it2->block = itbn;
+                       itb->items = eina_list_remove_list(itb->items, last);
+                       itbn->items = eina_list_prepend(itbn->items, it2);
+                       itbn->count++;
+                       itbn->changed = EINA_TRUE;
+                    }
+                  it->wd->blocks =
+                    eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
+                  free(itb);
+               }
+          }
+     }
+}
+
+static void
+_item_del(Elm_Genlist_Item *it)
+{
+   elm_widget_item_pre_notify_del(it);
+   elm_genlist_item_subitems_clear(it);
+   it->wd->walking -= it->walking;
+   if (it->wd->show_item == it) it->wd->show_item = NULL;
+   if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
+   if (it->realized) _item_unrealize(it);
+   if (it->block) _item_block_del(it);
+   if ((!it->delete_me) && (it->itc->func.del))
+     it->itc->func.del((void *)it->base.data, it->base.widget);
+   it->delete_me = EINA_TRUE;
+   if (it->queued)
+     it->wd->queue = eina_list_remove(it->wd->queue, it);
+   if (it->wd->anchor_item == it)
+     {
+        it->wd->anchor_item = (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->next);
+        if (!it->wd->anchor_item)
+          it->wd->anchor_item = (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->prev);
+     }
+   it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
+   if (it->parent)
+     it->parent->items = eina_list_remove(it->parent->items, it);
+   if (it->flags & ELM_GENLIST_ITEM_GROUP)
+     it->wd->group_items = eina_list_remove(it->wd->group_items, it);
+   if (it->long_timer) ecore_timer_del(it->long_timer);
+   if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
+
+   if (it->tooltip.del_cb)
+     it->tooltip.del_cb((void *)it->tooltip.data, it->base.widget, it);
+
+   elm_widget_item_del(it);
+}
+
+static void
+_item_select(Elm_Genlist_Item *it)
+{
+   if ((it->wd->no_select) || (it->delete_me)) return;
+   if (it->selected)
+     {
+        if (it->wd->always_select) goto call;
+        return;
+     }
+   it->selected = EINA_TRUE;
+   it->wd->selected = eina_list_append(it->wd->selected, it);
+call:
+   it->walking++;
+   it->wd->walking++;
+   if (it->func.func) it->func.func((void *)it->func.data, it->base.widget, it);
+   if (!it->delete_me)
+     evas_object_smart_callback_call(it->base.widget, "selected", it);
+   it->walking--;
+   it->wd->walking--;
+   if ((it->wd->clear_me) && (!it->wd->walking))
+     elm_genlist_clear(it->base.widget);
+   else
+     {
+        if ((!it->walking) && (it->delete_me))
+          {
+             if (!it->relcount) _item_del(it);
+          }
+     }
+   it->wd->last_selected_item = it;
+}
+
+static void
+_item_unselect(Elm_Genlist_Item *it)
+{
+   const char *stacking, *selectraise;
+
+   if ((it->delete_me) || (!it->hilighted)) return;
+   edje_object_signal_emit(it->base.view, "elm,state,unselected", "elm");
+   stacking = edje_object_data_get(it->base.view, "stacking");
+   selectraise = edje_object_data_get(it->base.view, "selectraise");
+   if ((selectraise) && (!strcmp(selectraise, "on")))
+     {
+        if ((stacking) && (!strcmp(stacking, "below")))
+          evas_object_lower(it->base.view);
+     }
+   it->hilighted = EINA_FALSE;
+   if (it->selected)
+     {
+        it->selected = EINA_FALSE;
+        it->wd->selected = eina_list_remove(it->wd->selected, it);
+        evas_object_smart_callback_call(it->base.widget, "unselected", it);
+     }
+}
+
+static void
+_mouse_move(void        *data,
+            Evas *evas   __UNUSED__,
+            Evas_Object *obj,
+            void        *event_info)
+{
+   Elm_Genlist_Item *it = 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 (!it->wd->on_hold)
+          {
+             it->wd->on_hold = EINA_TRUE;
+             if (!it->wd->wasselected)
+               _item_unselect(it);
+          }
+     }
+   if (it->wd->multitouched)
+     {
+        it->wd->cur_x = ev->cur.canvas.x;
+        it->wd->cur_y = ev->cur.canvas.y;
+        return;
+     }
+   if ((it->dragging) && (it->down))
+     {
+        if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
+        else
+          {
+             it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
+             it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
+             if (abs((it->wd->history[it->wd->movements].x -
+                      it->wd->history[0].x)) > 40)
+               it->wd->swipe = EINA_TRUE;
+             else
+               it->wd->movements++;
+          }
+        if (it->long_timer)
+          {
+             ecore_timer_del(it->long_timer);
+             it->long_timer = NULL;
+          }
+        evas_object_smart_callback_call(it->base.widget, "drag", it);
+        return;
+     }
+   if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
+     {
+        if (it->long_timer)
+          {
+             ecore_timer_del(it->long_timer);
+             it->long_timer = NULL;
+          }
+        return;
+     }
+   if (!it->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 - it->dx;
+   adx = dx;
+   if (adx < 0) adx = -dx;
+   dy = y - it->dy;
+   ady = dy;
+   if (ady < 0) ady = -dy;
+   minw /= 2;
+   minh /= 2;
+   if ((adx > minw) || (ady > minh))
+     {
+        it->dragging = EINA_TRUE;
+        if (it->long_timer)
+          {
+             ecore_timer_del(it->long_timer);
+             it->long_timer = NULL;
+          }
+        if (!it->wd->wasselected)
+          _item_unselect(it);
+        if (dy < 0)
+          {
+             if (ady > adx)
+               evas_object_smart_callback_call(it->base.widget,
+                                               "drag,start,up", it);
+             else
+               {
+                  if (dx < 0)
+                    evas_object_smart_callback_call(it->base.widget,
+                                                    "drag,start,left", it);
+                  else
+                    evas_object_smart_callback_call(it->base.widget,
+                                                    "drag,start,right", it);
+               }
+          }
+        else
+          {
+             if (ady > adx)
+               evas_object_smart_callback_call(it->base.widget,
+                                               "drag,start,down", it);
+             else
+               {
+                  if (dx < 0)
+                    evas_object_smart_callback_call(it->base.widget,
+                                                    "drag,start,left", it);
+                  else
+                    evas_object_smart_callback_call(it->base.widget,
+                                                    "drag,start,right", it);
+               }
+          }
+     }
+}
+
+static Eina_Bool
+_long_press(void *data)
+{
+   Elm_Genlist_Item *it = data;
+
+   it->long_timer = NULL;
+   if ((it->disabled) || (it->dragging) || (it->display_only))
+     return ECORE_CALLBACK_CANCEL;
+   it->wd->longpressed = EINA_TRUE;
+   evas_object_smart_callback_call(it->base.widget, "longpressed", it);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_swipe(Elm_Genlist_Item *it)
+{
+   int i, sum = 0;
+
+   if (!it) return;
+   it->wd->swipe = EINA_FALSE;
+   for (i = 0; i < it->wd->movements; i++)
+     {
+        sum += it->wd->history[i].x;
+        if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
+     }
+
+   sum /= it->wd->movements;
+   if (abs(sum - it->wd->history[0].x) <= 10) return;
+   evas_object_smart_callback_call(it->base.widget, "swipe", it);
+}
+
+static Eina_Bool
+_swipe_cancel(void *data)
+{
+   Elm_Genlist_Item *it = data;
+
+   if (!it) return ECORE_CALLBACK_CANCEL;
+   it->wd->swipe = EINA_FALSE;
+   it->wd->movements = 0;
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_multi_cancel(void *data)
+{
+   Widget_Data *wd = data;
+
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->multi_timeout = EINA_TRUE;
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_multi_touch_gesture_eval(void *data)
+{
+   Elm_Genlist_Item *it = data;
+
+   it->wd->multitouched = EINA_FALSE;
+   if (it->wd->multi_timer)
+     {
+        ecore_timer_del(it->wd->multi_timer);
+        it->wd->multi_timer = NULL;
+     }
+   if (it->wd->multi_timeout)
+     {
+         it->wd->multi_timeout = EINA_FALSE;
+         return;
+     }
+
+   Evas_Coord minw = 0, minh = 0;
+   Evas_Coord off_x, off_y, off_mx, off_my;
+
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   off_x = abs(it->wd->cur_x - it->wd->prev_x);
+   off_y = abs(it->wd->cur_y - it->wd->prev_y);
+   off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
+   off_my = abs(it->wd->cur_my - it->wd->prev_my);
+
+   if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
+     {
+        if ((off_x + off_mx) > (off_y + off_my))
+          {
+             if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,swipe,right", it);
+             else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,swipe,left", it);
+             else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,pinch,out", it);
+             else
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,pinch,in", it);
+          }
+        else
+          {
+             if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,swipe,down", it);
+             else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,swipe,up", it);
+             else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,pinch,out", it);
+             else
+               evas_object_smart_callback_call(it->base.widget,
+                                               "multi,pinch,in", it);
+          }
+     }
+     it->wd->multi_timeout = EINA_FALSE;
+}
+
+static void
+_multi_down(void        *data,
+            Evas *evas  __UNUSED__,
+            Evas_Object *obj __UNUSED__,
+            void        *event_info)
+{
+   Elm_Genlist_Item *it = data;
+   Evas_Event_Multi_Down *ev = event_info;
+
+   if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
+   it->wd->multi_device = ev->device;
+   it->wd->multi_down = EINA_TRUE;
+   it->wd->multitouched = EINA_TRUE;
+   it->wd->prev_mx = ev->canvas.x;
+   it->wd->prev_my = ev->canvas.y;
+   if (!it->wd->wasselected) _item_unselect(it);
+   it->wd->wasselected = EINA_FALSE;
+   it->wd->longpressed = EINA_FALSE;
+   if (it->long_timer)
+     {
+        ecore_timer_del(it->long_timer);
+        it->long_timer = NULL;
+     }
+   if (it->dragging)
+     {
+        it->dragging = EINA_FALSE;
+        evas_object_smart_callback_call(it->base.widget, "drag,stop", it);
+     }
+   if (it->swipe_timer)
+     {
+        ecore_timer_del(it->swipe_timer);
+        it->swipe_timer = NULL;
+     }
+   if (it->wd->on_hold)
+     {
+        it->wd->swipe = EINA_FALSE;
+        it->wd->movements = 0;
+        it->wd->on_hold = EINA_FALSE;
+     }
+}
+
+static void
+_multi_up(void        *data,
+          Evas *evas  __UNUSED__,
+          Evas_Object *obj __UNUSED__,
+          void        *event_info)
+{
+   Elm_Genlist_Item *it = data;
+   Evas_Event_Multi_Up *ev = event_info;
+
+   if (it->wd->multi_device != ev->device) return;
+   it->wd->multi_device = 0;
+   it->wd->multi_down = EINA_FALSE;
+   if (it->wd->mouse_down) return;
+   _multi_touch_gesture_eval(data);
+}
+
+static void
+_multi_move(void        *data,
+            Evas *evas  __UNUSED__,
+            Evas_Object *obj __UNUSED__,
+            void        *event_info)
+{
+   Elm_Genlist_Item *it = data;
+   Evas_Event_Multi_Move *ev = event_info;
+
+   if (it->wd->multi_device != ev->device) return;
+   it->wd->cur_mx = ev->cur.canvas.x;
+   it->wd->cur_my = ev->cur.canvas.y;
+}
+
+static void
+_mouse_down(void        *data,
+            Evas *evas   __UNUSED__,
+            Evas_Object *obj,
+            void        *event_info)
+{
+   Elm_Genlist_Item *it = data;
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord x, y;
+
+   if (ev->button != 1) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     {
+        it->wd->on_hold = EINA_TRUE;
+     }
+
+   it->down = EINA_TRUE;
+   it->dragging = EINA_FALSE;
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   it->dx = ev->canvas.x - x;
+   it->dy = ev->canvas.y - y;
+   it->wd->mouse_down = EINA_TRUE;
+   if (!it->wd->multitouched)
+     {
+        it->wd->prev_x = ev->canvas.x;
+        it->wd->prev_y = ev->canvas.y;
+        it->wd->multi_timeout = EINA_FALSE;
+        if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
+        it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
+     }
+   it->wd->longpressed = EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
+   else it->wd->on_hold = EINA_FALSE;
+   if (it->wd->on_hold) return;
+   it->wd->wasselected = it->selected;
+   _item_hilight(it);
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     evas_object_smart_callback_call(it->base.widget, "clicked", it);
+   if (it->long_timer) ecore_timer_del(it->long_timer);
+   if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
+   it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
+   if (it->realized)
+     it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
+                                      it);
+   else
+     it->long_timer = NULL;
+   it->wd->swipe = EINA_FALSE;
+   it->wd->movements = 0;
+}
+
+static void
+_mouse_up(void            *data,
+          Evas *evas       __UNUSED__,
+          Evas_Object *obj __UNUSED__,
+          void            *event_info)
+{
+   Elm_Genlist_Item *it = data;
+   Evas_Event_Mouse_Up *ev = event_info;
+   Eina_Bool dragged = EINA_FALSE;
+
+   if (ev->button != 1) return;
+   it->down = EINA_FALSE;
+   it->wd->mouse_down = EINA_FALSE;
+   if (it->wd->multitouched)
+     {
+        if (it->wd->multi_down) return;
+        _multi_touch_gesture_eval(data);
+        return;
+     }
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
+   else it->wd->on_hold = EINA_FALSE;
+   if (it->long_timer)
+     {
+        ecore_timer_del(it->long_timer);
+        it->long_timer = NULL;
+     }
+   if (it->dragging)
+     {
+        it->dragging = EINA_FALSE;
+        evas_object_smart_callback_call(it->base.widget, "drag,stop", it);
+        dragged = 1;
+     }
+   if (it->swipe_timer)
+     {
+        ecore_timer_del(it->swipe_timer);
+        it->swipe_timer = NULL;
+     }
+   if (it->wd->multi_timer)
+     {
+        ecore_timer_del(it->wd->multi_timer);
+        it->wd->multi_timer = NULL;
+        it->wd->multi_timeout = EINA_FALSE;
+     }
+   if (it->wd->on_hold)
+     {
+        if (it->wd->swipe) _swipe(data);
+        it->wd->longpressed = EINA_FALSE;
+        it->wd->on_hold = EINA_FALSE;
+        return;
+     }
+   if (it->wd->longpressed)
+     {
+        it->wd->longpressed = EINA_FALSE;
+        if (!it->wd->wasselected)
+          _item_unselect(it);
+        it->wd->wasselected = EINA_FALSE;
+        return;
+     }
+   if (dragged)
+     {
+        if (it->want_unrealize)
+          {
+             _item_unrealize(it);
+             if (it->block->want_unrealize)
+               _item_block_unrealize(it->block);
+          }
+     }
+   if ((it->disabled) || (dragged) || (it->display_only)) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+   if (it->wd->multi)
+     {
+        if (!it->selected)
+          {
+             _item_hilight(it);
+             _item_select(it);
+          }
+        else _item_unselect(it);
+     }
+   else
+     {
+        if (!it->selected)
+          {
+             Widget_Data *wd = it->wd;
+             if (wd)
+               {
+                  while (wd->selected) _item_unselect(wd->selected->data);
+               }
+          }
+        else
+          {
+             const Eina_List *l, *l_next;
+             Elm_Genlist_Item *it2;
+
+             EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
+               if (it2 != it) _item_unselect(it2);
+             //_item_hilight(it);
+             //_item_select(it);
+          }
+        _item_hilight(it);
+        _item_select(it);
+     }
+}
+
+static void
+_signal_expand_toggle(void                *data,
+                      Evas_Object *obj     __UNUSED__,
+                      const char *emission __UNUSED__,
+                      const char *source   __UNUSED__)
+{
+   Elm_Genlist_Item *it = data;
+
+   if (it->expanded)
+     evas_object_smart_callback_call(it->base.widget, "contract,request", it);
+   else
+     evas_object_smart_callback_call(it->base.widget, "expand,request", it);
+}
+
+static void
+_signal_expand(void                *data,
+               Evas_Object *obj     __UNUSED__,
+               const char *emission __UNUSED__,
+               const char *source   __UNUSED__)
+{
+   Elm_Genlist_Item *it = data;
+
+   if (!it->expanded)
+     evas_object_smart_callback_call(it->base.widget, "expand,request", it);
+}
+
+static void
+_signal_contract(void                *data,
+                 Evas_Object *obj     __UNUSED__,
+                 const char *emission __UNUSED__,
+                 const char *source   __UNUSED__)
+{
+   Elm_Genlist_Item *it = data;
+
+   if (it->expanded)
+     evas_object_smart_callback_call(it->base.widget, "contract,request", it);
+}
+
+static void
+_item_cache_clean(Widget_Data *wd)
+{
+   while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
+     {
+        Item_Cache *itc;
+
+        itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
+        wd->item_cache = eina_inlist_remove(wd->item_cache,
+                                            wd->item_cache->last);
+        wd->item_cache_count--;
+        if (itc->spacer) evas_object_del(itc->spacer);
+        if (itc->base_view) evas_object_del(itc->base_view);
+        if (itc->item_style) eina_stringshare_del(itc->item_style);
+        free(itc);
+     }
+}
+
+static void
+_item_cache_zero(Widget_Data *wd)
+{
+   int pmax = wd->item_cache_max;
+   wd->item_cache_max = 0;
+   _item_cache_clean(wd);
+   wd->item_cache_max = pmax;
+}
+
+static void
+_item_cache_add(Elm_Genlist_Item *it)
+{
+   Item_Cache *itc;
+
+   if (it->wd->item_cache_max <= 0)
+     {
+        evas_object_del(it->base.view);
+        it->base.view = NULL;
+        evas_object_del(it->spacer);
+        it->spacer = NULL;
+        return;
+     }
+
+   it->wd->item_cache_count++;
+   itc = calloc(1, sizeof(Item_Cache));
+   it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
+                                            EINA_INLIST_GET(itc));
+   itc->spacer = it->spacer;
+   it->spacer = NULL;
+   itc->base_view = it->base.view;
+   it->base.view = NULL;
+   evas_object_hide(itc->base_view);
+   evas_object_move(itc->base_view, -9999, -9999);
+   itc->item_style = eina_stringshare_add(it->itc->item_style);
+   if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) itc->tree = 1;
+   itc->compress = (it->wd->compress);
+   itc->odd = (it->order_num_in & 0x1);
+   itc->selected = it->selected;
+   itc->disabled = it->disabled;
+   itc->expanded = it->expanded;
+   if (it->long_timer)
+     {
+        ecore_timer_del(it->long_timer);
+        it->long_timer = NULL;
+     }
+   if (it->swipe_timer)
+     {
+        ecore_timer_del(it->swipe_timer);
+        it->swipe_timer = NULL;
+     }
+   // FIXME: other callbacks?
+   edje_object_signal_callback_del_full(itc->base_view,
+                                        "elm,action,expand,toggle",
+                                        "elm", _signal_expand_toggle, it);
+   edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
+                                        "elm",
+                                        _signal_expand, it);
+   edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
+                                        "elm", _signal_contract, it);
+   evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_DOWN,
+                                       _mouse_down, it);
+   evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_UP,
+                                       _mouse_up, it);
+   evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_MOVE,
+                                       _mouse_move, it);
+   evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_DOWN,
+                                       _multi_down, it);
+   evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_UP,
+                                       _multi_up, it);
+   evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
+                                       _multi_move, it);
+   _item_cache_clean(it->wd);
+}
+
+static Item_Cache *
+_item_cache_find(Elm_Genlist_Item *it)
+{
+   Item_Cache *itc;
+   Eina_Bool tree = 0, odd;
+
+   if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) tree = 1;
+   odd = (it->order_num_in & 0x1);
+   EINA_INLIST_FOREACH(it->wd->item_cache, itc)
+   {
+      if ((itc->selected) || (itc->disabled) || (itc->expanded))
+        continue;
+      if ((itc->tree == tree) &&
+          (itc->odd == odd) &&
+          (itc->compress == it->wd->compress) &&
+          (!strcmp(it->itc->item_style, itc->item_style)))
+        {
+           it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
+                                                   EINA_INLIST_GET(itc));
+           it->wd->item_cache_count--;
+           return itc;
+        }
+   }
+   return NULL;
+}
+
+static void
+_item_cache_free(Item_Cache *itc)
+{
+   if (itc->spacer) evas_object_del(itc->spacer);
+   if (itc->base_view) evas_object_del(itc->base_view);
+   if (itc->item_style) eina_stringshare_del(itc->item_style);
+   free(itc);
+}
+
+static void
+_item_realize(Elm_Genlist_Item *it,
+              int               in,
+              int               calc)
+{
+   Elm_Genlist_Item *it2;
+   const char *stacking;
+   const char *treesize;
+   char buf[1024];
+   int depth, tsize = 20;
+   Item_Cache *itc;
+
+   if ((it->realized) || (it->delete_me)) return;
+   it->order_num_in = in;
+
+   itc = _item_cache_find(it);
+   if (itc)
+     {
+        it->base.view = itc->base_view;
+        itc->base_view = NULL;
+        it->spacer = itc->spacer;
+        itc->spacer = NULL;
+     }
+   else
+     {
+        it->base.view = edje_object_add(evas_object_evas_get(it->base.widget));
+        edje_object_scale_set(it->base.view,
+                              elm_widget_scale_get(it->base.widget) *
+                              _elm_config->scale);
+        evas_object_smart_member_add(it->base.view, it->wd->pan_smart);
+        elm_widget_sub_object_add(it->base.widget, it->base.view);
+
+        if (it->flags & ELM_GENLIST_ITEM_SUBITEMS)
+          strncpy(buf, "tree", sizeof(buf));
+        else strncpy(buf, "item", sizeof(buf));
+        if (it->wd->compress)
+          strncat(buf, "_compress", sizeof(buf) - strlen(buf));
+
+        if (in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
+        strncat(buf, "/", sizeof(buf) - strlen(buf));
+        strncat(buf, it->itc->item_style, sizeof(buf) - strlen(buf));
+
+        _elm_theme_object_set(it->base.widget, it->base.view, "genlist", buf,
+                              elm_widget_style_get(it->base.widget));
+        it->spacer =
+          evas_object_rectangle_add(evas_object_evas_get(it->base.widget));
+        evas_object_color_set(it->spacer, 0, 0, 0, 0);
+        elm_widget_sub_object_add(it->base.widget, it->spacer);
+     }
+   for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
+     {
+        if (it2->parent->flags != ELM_GENLIST_ITEM_GROUP) depth += 1;
+     }
+   it->expanded_depth = depth;
+   treesize = edje_object_data_get(it->base.view, "treesize");
+   if (treesize) tsize = atoi(treesize);
+   evas_object_size_hint_min_set(it->spacer,
+                                 (depth * tsize) * _elm_config->scale, 1);
+   edje_object_part_swallow(it->base.view, "elm.swallow.pad", it->spacer);
+   if (!calc)
+     {
+        edje_object_signal_callback_add(it->base.view,
+                                        "elm,action,expand,toggle",
+                                        "elm", _signal_expand_toggle, it);
+        edje_object_signal_callback_add(it->base.view, "elm,action,expand",
+                                        "elm", _signal_expand, it);
+        edje_object_signal_callback_add(it->base.view, "elm,action,contract",
+                                        "elm", _signal_contract, it);
+        stacking = edje_object_data_get(it->base.view, "stacking");
+        if (stacking)
+          {
+             if (!strcmp(stacking, "below")) evas_object_lower(it->base.view);
+             else if (!strcmp(stacking, "above"))
+               evas_object_raise(it->base.view);
+          }
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_DOWN,
+                                       _mouse_down, it);
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_UP,
+                                       _mouse_up, it);
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_MOVE,
+                                       _mouse_move, it);
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MULTI_DOWN,
+                                       _multi_down, it);
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MULTI_UP,
+                                       _multi_up, it);
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MULTI_MOVE,
+                                       _multi_move, it);
+        if (itc)
+          {
+             if (it->selected != itc->selected)
+               {
+                  if (it->selected)
+                    edje_object_signal_emit(it->base.view,
+                                            "elm,state,selected", "elm");
+               }
+             if (it->disabled != itc->disabled)
+               {
+                  if (it->disabled)
+                    edje_object_signal_emit(it->base.view,
+                                            "elm,state,disabled", "elm");
+               }
+             if (it->expanded != itc->expanded)
+               {
+                  if (it->expanded)
+                    edje_object_signal_emit(it->base.view,
+                                            "elm,state,expanded", "elm");
+               }
+          }
+        else
+          {
+             if (it->selected)
+               edje_object_signal_emit(it->base.view,
+                                       "elm,state,selected", "elm");
+             if (it->disabled)
+               edje_object_signal_emit(it->base.view,
+                                       "elm,state,disabled", "elm");
+             if (it->expanded)
+               edje_object_signal_emit(it->base.view,
+                                       "elm,state,expanded", "elm");
+          }
+     }
+
+   if ((calc) && (it->wd->homogeneous) && (it->wd->item_width))
+     {
+        /* homogenous genlist shortcut */
+         if (!it->mincalcd)
+           {
+              it->w = it->minw = it->wd->item_width;
+              it->h = it->minh = it->wd->item_height;
+              it->mincalcd = EINA_TRUE;
+           }
+     }
+   else
+     {
+        if (it->itc->func.label_get)
+          {
+             const Eina_List *l;
+             const char *key;
+
+             it->labels =
+               elm_widget_stringlist_get(edje_object_data_get(it->base.view,
+                                                              "labels"));
+             EINA_LIST_FOREACH(it->labels, l, key)
+               {
+                  char *s = it->itc->func.label_get
+                      ((void *)it->base.data, it->base.widget, l->data);
+
+                  if (s)
+                    {
+                       edje_object_part_text_set(it->base.view, l->data, s);
+                       free(s);
+                    }
+                  else if (itc)
+                    edje_object_part_text_set(it->base.view, l->data, "");
+               }
+          }
+        if (it->itc->func.icon_get)
+          {
+             const Eina_List *l;
+             const char *key;
+
+             it->icons =
+               elm_widget_stringlist_get(edje_object_data_get(it->base.view,
+                                                              "icons"));
+             EINA_LIST_FOREACH(it->icons, l, key)
+               {
+                  Evas_Object *ic = it->itc->func.icon_get
+                      ((void *)it->base.data, it->base.widget, l->data);
+
+                  if (ic)
+                    {
+                       it->icon_objs = eina_list_append(it->icon_objs, ic);
+                       edje_object_part_swallow(it->base.view, key, ic);
+                       evas_object_show(ic);
+                       elm_widget_sub_object_add(it->base.widget, ic);
+                    }
+               }
+          }
+        if (it->itc->func.state_get)
+          {
+             const Eina_List *l;
+             const char *key;
+
+             it->states =
+               elm_widget_stringlist_get(edje_object_data_get(it->base.view,
+                                                              "states"));
+             EINA_LIST_FOREACH(it->states, l, key)
+               {
+                  Eina_Bool on = it->itc->func.state_get
+                      ((void *)it->base.data, it->base.widget, l->data);
+
+                  if (on)
+                    {
+                       snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
+                       edje_object_signal_emit(it->base.view, buf, "elm");
+                    }
+                  else if (itc)
+                    {
+                       snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
+                       edje_object_signal_emit(it->base.view, buf, "elm");
+                    }
+               }
+          }
+        if (!it->mincalcd)
+          {
+             Evas_Coord mw = -1, mh = -1;
+
+             if (it->wd->height_for_width) mw = it->wd->w;
+
+             if (!it->display_only)
+               elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+             if (it->wd->height_for_width) mw = it->wd->prev_viewport_w;
+             edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw,
+                                                  mh);
+             if (!it->display_only)
+               elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+             it->w = it->minw = mw;
+             it->h = it->minh = mh;
+             it->mincalcd = EINA_TRUE;
+
+             if ((!in) && (it->wd->homogeneous))
+               {
+                  it->wd->item_width = mw;
+                  it->wd->item_height = mh;
+               }
+          }
+        if (!calc) evas_object_show(it->base.view);
+     }
+
+   if (it->tooltip.content_cb)
+     {
+        elm_widget_item_tooltip_content_cb_set(it,
+                                               it->tooltip.content_cb,
+                                               it->tooltip.data, NULL);
+        elm_widget_item_tooltip_style_set(it, it->tooltip.style);
+     }
+
+   if (it->mouse_cursor)
+     elm_widget_item_cursor_set(it, it->mouse_cursor);
+
+   it->realized = EINA_TRUE;
+   it->want_unrealize = EINA_FALSE;
+
+   if (itc) _item_cache_free(itc);
+   evas_object_smart_callback_call(it->base.widget, "realized", it);
+}
+
+static void
+_item_unrealize(Elm_Genlist_Item *it)
+{
+   Evas_Object *icon;
+
+   if (!it->realized) return;
+   evas_object_smart_callback_call(it->base.widget, "unrealized", it);
+   if (it->long_timer)
+     {
+        ecore_timer_del(it->long_timer);
+        it->long_timer = NULL;
+     }
+   _item_cache_add(it);
+   elm_widget_stringlist_free(it->labels);
+   it->labels = NULL;
+   elm_widget_stringlist_free(it->icons);
+   it->icons = NULL;
+   elm_widget_stringlist_free(it->states);
+
+   EINA_LIST_FREE(it->icon_objs, icon)
+     evas_object_del(icon);
+
+   it->states = NULL;
+   it->realized = EINA_FALSE;
+   it->want_unrealize = EINA_FALSE;
+}
+
+static Eina_Bool 
+_item_block_recalc(Item_Block *itb,
+                   int         in,
+                   int         qadd,
+                   int         norender)
+{
+   const Eina_List *l;
+   Elm_Genlist_Item *it;
+   Evas_Coord minw = 0, minh = 0;
+   Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
+   Evas_Coord y = 0;
+
+   itb->num = in;
+   EINA_LIST_FOREACH(itb->items, l, it)
+     {
+        if (it->delete_me) continue;
+        showme |= it->showme;
+        if (!itb->realized)
+          {
+             if (qadd)
+               {
+                  if (!it->mincalcd) changed = EINA_TRUE;
+                  if (changed)
+                    {
+                       _item_realize(it, in, 1);
+                       _item_unrealize(it);
+                    }
+               }
+             else
+               {
+                  _item_realize(it, in, 1);
+                  _item_unrealize(it);
+               }
+          }
+        else
+          _item_realize(it, in, 0);
+        minh += it->minh;
+        if (minw < it->minw) minw = it->minw;
+        in++;
+        it->x = 0;
+        it->y = y;
+        y += it->h;
+     }
+   itb->minw = minw;
+   itb->minh = minh;
+   itb->changed = EINA_FALSE;
+   /* force an evas norender to garbage collect deleted objects */
+   if (norender) evas_norender(evas_object_evas_get(itb->wd->obj));
+   return showme;
+}
+
+static void
+_item_block_realize(Item_Block *itb,
+                    int         in,
+                    int         full)
+{
+   const Eina_List *l;
+   Elm_Genlist_Item *it;
+
+   if (itb->realized) return;
+   EINA_LIST_FOREACH(itb->items, l, it)
+     {
+        if (it->delete_me) continue;
+        if (full) _item_realize(it, in, 0);
+        in++;
+     }
+   itb->realized = EINA_TRUE;
+   itb->want_unrealize = EINA_FALSE;
+}
+
+static void
+_item_block_unrealize(Item_Block *itb)
+{
+   const Eina_List *l;
+   Elm_Genlist_Item *it;
+   Eina_Bool dragging = EINA_FALSE;
+
+   if (!itb->realized) return;
+   EINA_LIST_FOREACH(itb->items, l, it)
+     {
+        if (it->flags != ELM_GENLIST_ITEM_GROUP)
+          {
+             if (it->dragging)
+               {
+                  dragging = EINA_TRUE;
+                  it->want_unrealize = EINA_TRUE;
+               }
+             else
+                _item_unrealize(it);
+          }
+     }
+   if (!dragging)
+     {
+        itb->realized = EINA_FALSE;
+        itb->want_unrealize = EINA_TRUE;
+     }
+   else
+     itb->want_unrealize = EINA_FALSE;
+}
+
+static void
+_item_block_position(Item_Block *itb,
+                     int         in)
+{
+   const Eina_List *l;
+   Elm_Genlist_Item *it;
+   Elm_Genlist_Item *git;
+   Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
+   int vis;
+
+   evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
+   evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
+                            &cvw, &cvh);
+   EINA_LIST_FOREACH(itb->items, l, it)
+     {
+        if (it->delete_me) continue;
+        it->x = 0;
+        it->y = y;
+        it->w = itb->w;
+        it->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
+        it->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
+
+        if (it->flags != ELM_GENLIST_ITEM_GROUP)
+          {
+             vis = (ELM_RECTS_INTERSECT(it->scrl_x, it->scrl_y, it->w, it->h,
+                                        cvx, cvy, cvw, cvh));
+             if ((itb->realized) && (!it->realized))
+               {
+                  if (vis) _item_realize(it, in, 0);
+               }
+             if (it->realized)
+               {
+                  if (vis)
+                    {
+                       git = it->group_item;
+                       if (git)
+                         {
+                            if (git->scrl_y < oy)
+                               git->scrl_y = oy;
+                            if ((git->scrl_y + git->h) > (it->scrl_y + it->h))
+                               git->scrl_y = (it->scrl_y + it->h) - git->h;
+                            git->want_realize = EINA_TRUE;
+                         }
+                       evas_object_resize(it->base.view, it->w, it->h);
+                       evas_object_move(it->base.view,
+                                        it->scrl_x, it->scrl_y);
+                       evas_object_show(it->base.view);
+                    }
+                  else
+                    {
+                       if (!it->dragging) _item_unrealize(it);
+                    }
+               }
+             in++;
+          }
+        y += it->h;
+     }
+}
+
+static void
+_group_items_recalc(void *data)
+{
+   Widget_Data *wd = data;
+   Eina_List *l;
+   Elm_Genlist_Item *git;
+
+   EINA_LIST_FOREACH(wd->group_items, l, git)
+     {
+        if (git->want_realize) 
+          {
+             if (!git->realized)
+                _item_realize(git, 0, 0);
+             evas_object_resize(git->base.view, wd->minw, git->h);
+             evas_object_move(git->base.view, git->scrl_x, git->scrl_y);
+             evas_object_show(git->base.view);
+             evas_object_raise(git->base.view);
+          }
+        else if (!git->want_realize && git->realized)
+          {
+             if (!git->dragging) 
+                _item_unrealize(git);
+          }
+     }
+}
+
+static Eina_Bool
+_must_recalc_idler(void *data)
+{
+   Widget_Data *wd = data;
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   wd->must_recalc_idler = NULL;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_calc_job(void *data)
+{
+   Widget_Data *wd = data;
+   Item_Block *itb;
+   Evas_Coord minw = -1, minh = 0, y = 0, ow;
+   Item_Block *chb = NULL;
+   int in = 0, minw_change = 0;
+   Eina_Bool changed = EINA_FALSE;
+   double t0, t;
+   Eina_Bool did_must_recalc = EINA_FALSE;
+   if (!wd) return;
+
+   t0 = ecore_time_get();
+   evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
+   if (wd->w != ow)
+     {
+        wd->w = ow;
+//        if (wd->height_for_width) changed = EINA_TRUE;
+     }
+
+   EINA_INLIST_FOREACH(wd->blocks, itb)
+   {
+      Eina_Bool showme = EINA_FALSE;
+
+      itb->num = in;
+      showme = itb->showme;
+      itb->showme = EINA_FALSE;
+      if (chb)
+        {
+           if (itb->realized) _item_block_unrealize(itb);
+        }
+      if ((itb->changed) || (changed) ||
+          ((itb->must_recalc) && (!did_must_recalc)))
+        {
+           if ((changed) || (itb->must_recalc))
+             {
+                Eina_List *l;
+                Elm_Genlist_Item *it;
+                EINA_LIST_FOREACH(itb->items, l, it)
+                  if (it->mincalcd) it->mincalcd = EINA_FALSE;
+                itb->changed = EINA_TRUE;
+                if (itb->must_recalc) did_must_recalc = EINA_TRUE;
+                itb->must_recalc = EINA_FALSE;
+             }
+           if (itb->realized) _item_block_unrealize(itb);
+           showme = _item_block_recalc(itb, in, 0, 1);
+           chb = itb;
+        }
+      itb->y = y;
+      itb->x = 0;
+      minh += itb->minh;
+      if (minw == -1) minw = itb->minw;
+      else if ((!itb->must_recalc) && (minw < itb->minw))
+        {
+           minw = itb->minw;
+           minw_change = 1;
+        }
+      itb->w = minw;
+      itb->h = itb->minh;
+      y += itb->h;
+      in += itb->count;
+      if ((showme) && (wd->show_item))
+        {
+           wd->show_item->showme = EINA_FALSE;
+           if (wd->bring_in)
+             elm_smart_scroller_region_bring_in(wd->scr,
+                                                wd->show_item->x +
+                                                wd->show_item->block->x,
+                                                wd->show_item->y +
+                                                wd->show_item->block->y,
+                                                wd->show_item->block->w,
+                                                wd->show_item->h);
+           else
+             elm_smart_scroller_child_region_show(wd->scr,
+                                                  wd->show_item->x +
+                                                  wd->show_item->block->x,
+                                                  wd->show_item->y +
+                                                  wd->show_item->block->y,
+                                                  wd->show_item->block->w,
+                                                  wd->show_item->h);
+           wd->show_item = NULL;
+        }
+   }
+   if (minw_change)
+     {
+        EINA_INLIST_FOREACH(wd->blocks, itb)
+        {
+           itb->minw = minw;
+           itb->w = itb->minw;
+        }
+     }
+   if ((chb) && (EINA_INLIST_GET(chb)->next))
+     {
+        EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
+        {
+           if (itb->realized) _item_block_unrealize(itb);
+        }
+     }
+   wd->realminw = minw;
+   if (minw < wd->w) minw = wd->w;
+   if ((minw != wd->minw) || (minh != wd->minh))
+     {
+        wd->minw = minw;
+        wd->minh = minh;
+        evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
+        _sizing_eval(wd->obj);
+        if ((wd->anchor_item) && (wd->anchor_item->block))
+          {
+             Elm_Genlist_Item *it;
+             Evas_Coord it_y;
+
+             it = wd->anchor_item;
+             it_y = wd->anchor_y;
+             elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
+                                              it->block->y + it->y + it_y);
+             wd->anchor_item = it;
+             wd->anchor_y = it_y;
+          }
+     }
+   t = ecore_time_get();
+   if (did_must_recalc)
+     {
+        if (!wd->must_recalc_idler)
+          wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
+     }
+   wd->calc_job = NULL;
+   evas_object_smart_changed(wd->pan_smart);
+}
+
+static void
+_update_job(void *data)
+{
+   Widget_Data *wd = data;
+   Eina_List *l2;
+   Item_Block *itb;
+   int num, num0, position = 0, recalc = 0;
+   if (!wd) return;
+   wd->update_job = NULL;
+   num = 0;
+   EINA_INLIST_FOREACH(wd->blocks, itb)
+   {
+      Evas_Coord itminw, itminh;
+      Elm_Genlist_Item *it;
+
+      if (!itb->updateme)
+        {
+           num += itb->count;
+           if (position)
+             _item_block_position(itb, num);
+           continue;
+        }
+      num0 = num;
+      recalc = 0;
+      EINA_LIST_FOREACH(itb->items, l2, it)
+        {
+           if (it->updateme)
+             {
+                itminw = it->w;
+                itminh = it->h;
+
+                it->updateme = EINA_FALSE;
+                if (it->realized)
+                  {
+                     _item_unrealize(it);
+                     _item_realize(it, num, 0);
+                     position = 1;
+                  }
+                else
+                  {
+                     _item_realize(it, num, 1);
+                     _item_unrealize(it);
+                  }
+                if ((it->minw != itminw) || (it->minh != itminh))
+                  recalc = 1;
+             }
+           num++;
+        }
+      itb->updateme = EINA_FALSE;
+      if (recalc)
+        {
+           position = 1;
+           itb->changed = EINA_TRUE;
+           _item_block_recalc(itb, num0, 0, 1);
+           _item_block_position(itb, num0);
+        }
+   }
+   if (position)
+     {
+        if (wd->calc_job) ecore_job_del(wd->calc_job);
+        wd->calc_job = ecore_job_add(_calc_job, wd);
+     }
+}
+
+static void
+_pan_set(Evas_Object *obj,
+         Evas_Coord   x,
+         Evas_Coord   y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   Item_Block *itb;
+
+//   Evas_Coord ow, oh;
+//   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
+//   ow = sd->wd->minw - ow;
+//   if (ow < 0) ow = 0;
+//   oh = sd->wd->minh - oh;
+//   if (oh < 0) oh = 0;
+//   if (x < 0) x = 0;
+//   if (y < 0) y = 0;
+//   if (x > ow) x = ow;
+//   if (y > oh) y = oh;
+   if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
+   sd->wd->pan_x = x;
+   sd->wd->pan_y = y;
+
+   EINA_INLIST_FOREACH(sd->wd->blocks, itb)
+   {
+      if ((itb->y + itb->h) > y)
+        {
+           Elm_Genlist_Item *it;
+           Eina_List *l2;
+
+           EINA_LIST_FOREACH(itb->items, l2, it)
+             {
+                if ((itb->y + it->y) >= y)
+                  {
+                     sd->wd->anchor_item = it;
+                     sd->wd->anchor_y = -(itb->y + it->y - y);
+                     goto done;
+                  }
+             }
+        }
+   }
+done:
+   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_max_get(Evas_Object *obj,
+             Evas_Coord  *x,
+             Evas_Coord  *y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   Evas_Coord ow, oh;
+
+   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
+   ow = sd->wd->minw - ow;
+   if (ow < 0) ow = 0;
+   oh = sd->wd->minh - oh;
+   if (oh < 0) oh = 0;
+   if (x) *x = ow;
+   if (y) *y = oh;
+}
+
+static void
+_pan_min_get(Evas_Object *obj __UNUSED__,
+             Evas_Coord      *x,
+             Evas_Coord      *y)
+{
+   if (x) *x = 0;
+   if (y) *y = 0;
+}
+
+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_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;
+   if (sd->resize_job)
+     {
+        ecore_job_del(sd->resize_job);
+        sd->resize_job = NULL;
+     }
+   _pan_sc.del(obj);
+}
+
+static void
+_pan_resize_job(void *data)
+{
+   Pan *sd = data;
+   _sizing_eval(sd->wd->obj);
+   sd->resize_job = NULL;
+}
+
+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->height_for_width) && (ow != w))
+     {
+        if (sd->resize_job) ecore_job_del(sd->resize_job);
+        sd->resize_job = ecore_job_add(_pan_resize_job, sd);
+     }
+   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);
+   Item_Block *itb;
+   Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
+   int in = 0;
+   Elm_Genlist_Item *git;
+   Eina_List *l;
+
+   evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
+   evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
+   EINA_LIST_FOREACH(sd->wd->group_items, l, git)
+     {
+        git->want_realize = EINA_FALSE;
+     }
+   EINA_INLIST_FOREACH(sd->wd->blocks, itb)
+   {
+      itb->w = sd->wd->minw;
+      if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
+                              itb->y - sd->wd->pan_y + oy,
+                              itb->w, itb->h,
+                              cvx, cvy, cvw, cvh))
+        {
+           if ((!itb->realized) || (itb->changed))
+             _item_block_realize(itb, in, 0);
+           _item_block_position(itb, in);
+        }
+      else
+        {
+           if (itb->realized) _item_block_unrealize(itb);
+        }
+      in += itb->count;
+   }
+   _group_items_recalc(sd->wd);
+}
+
+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->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
+_scroll_edge_left(void            *data,
+                  Evas_Object *scr __UNUSED__,
+                  void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,left", NULL);
+}
+
+static void
+_scroll_edge_right(void            *data,
+                   Evas_Object *scr __UNUSED__,
+                   void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,right", NULL);
+}
+
+static void
+_scroll_edge_top(void            *data,
+                 Evas_Object *scr __UNUSED__,
+                 void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,top", NULL);
+}
+
+static void
+_scroll_edge_bottom(void            *data,
+                    Evas_Object *scr __UNUSED__,
+                    void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,bottom", NULL);
+}
+
+/**
+ * Add a new Genlist object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Genlist
+ */
+EAPI Evas_Object *
+elm_genlist_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord minw, minh;
+   static Evas_Smart *smart = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   if (!smart)
+     {
+        static Evas_Smart_Class sc;
+
+        evas_object_smart_clipped_smart_set(&_pan_sc);
+        sc = _pan_sc;
+        sc.name = "elm_genlist_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;
+        if (!(smart = evas_smart_class_new(&sc))) return NULL;
+     }
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "genlist");
+   elm_widget_type_set(obj, "genlist");
+   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_del_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_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, "genlist", "base",
+                                       elm_widget_style_get(obj));
+   elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
+                                       _elm_config->thumbscroll_bounce_enable);
+   elm_widget_resize_object_set(obj, wd->scr);
+
+   evas_object_smart_callback_add(wd->scr, "edge,left", _scroll_edge_left, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,right", _scroll_edge_right,
+                                  obj);
+   evas_object_smart_callback_add(wd->scr, "edge,top", _scroll_edge_top, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,bottom", _scroll_edge_bottom,
+                                  obj);
+
+   wd->obj = obj;
+   wd->mode = ELM_LIST_SCROLL;
+   wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
+   wd->item_cache_max = wd->max_items_per_block * 2;
+   wd->longpress_timeout = _elm_config->longpress_timeout;
+
+   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->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_min_get, _pan_child_size_get);
+
+   edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
+                             &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+static Elm_Genlist_Item *
+_item_new(Widget_Data                  *wd,
+          const Elm_Genlist_Item_Class *itc,
+          const void                   *data,
+          Elm_Genlist_Item             *parent,
+          Elm_Genlist_Item_Flags        flags,
+          Evas_Smart_Cb                 func,
+          const void                   *func_data)
+{
+   Elm_Genlist_Item *it;
+
+   it = elm_widget_item_new(wd->obj, Elm_Genlist_Item);
+   if (!it) return NULL;
+   it->wd = wd;
+   it->itc = itc;
+   it->base.data = data;
+   it->parent = parent;
+   it->flags = flags;
+   it->func.func = func;
+   it->func.data = func_data;
+   it->mouse_cursor = NULL;
+   it->expanded_depth = 0;
+   return it;
+}
+
+static void
+_item_block_add(Widget_Data      *wd,
+                Elm_Genlist_Item *it)
+{
+   Item_Block *itb = NULL;
+
+   if (!it->rel)
+     {
+newblock:
+        if (it->rel)
+          {
+             itb = calloc(1, sizeof(Item_Block));
+             if (!itb) return;
+             itb->wd = wd;
+             if (!it->rel->block)
+               {
+                  wd->blocks =
+                    eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
+                  itb->items = eina_list_append(itb->items, it);
+               }
+             else
+               {
+                  if (it->before)
+                    {
+                       wd->blocks = eina_inlist_prepend_relative
+                           (wd->blocks, EINA_INLIST_GET(itb),
+                           EINA_INLIST_GET(it->rel->block));
+                       itb->items =
+                         eina_list_prepend_relative(itb->items, it, it->rel);
+                    }
+                  else
+                    {
+                       wd->blocks = eina_inlist_append_relative
+                           (wd->blocks, EINA_INLIST_GET(itb),
+                           EINA_INLIST_GET(it->rel->block));
+                       itb->items =
+                         eina_list_append_relative(itb->items, it, it->rel);
+                    }
+               }
+          }
+        else
+          {
+             if (it->before)
+               {
+                  if (wd->blocks)
+                    {
+                       itb = (Item_Block *)(wd->blocks);
+                       if (itb->count >= wd->max_items_per_block)
+                         {
+                            itb = calloc(1, sizeof(Item_Block));
+                            if (!itb) return;
+                            itb->wd = wd;
+                            wd->blocks =
+                              eina_inlist_prepend(wd->blocks,
+                                                  EINA_INLIST_GET(itb));
+                         }
+                    }
+                  else
+                    {
+                       itb = calloc(1, sizeof(Item_Block));
+                       if (!itb) return;
+                       itb->wd = wd;
+                       wd->blocks =
+                         eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
+                    }
+                  itb->items = eina_list_prepend(itb->items, it);
+               }
+             else
+               {
+                  if (wd->blocks)
+                    {
+                       itb = (Item_Block *)(wd->blocks->last);
+                       if (itb->count >= wd->max_items_per_block)
+                         {
+                            itb = calloc(1, sizeof(Item_Block));
+                            if (!itb) return;
+                            itb->wd = wd;
+                            wd->blocks =
+                              eina_inlist_append(wd->blocks,
+                                                 EINA_INLIST_GET(itb));
+                         }
+                    }
+                  else
+                    {
+                       itb = calloc(1, sizeof(Item_Block));
+                       if (!itb) return;
+                       itb->wd = wd;
+                       wd->blocks =
+                         eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
+                    }
+                  itb->items = eina_list_append(itb->items, it);
+               }
+          }
+     }
+   else
+     {
+        itb = it->rel->block;
+        if (!itb) goto newblock;
+        if (it->before)
+          itb->items = eina_list_prepend_relative(itb->items, it, it->rel);
+        else
+          itb->items = eina_list_append_relative(itb->items, it, it->rel);
+     }
+   itb->count++;
+   itb->changed = EINA_TRUE;
+   it->block = itb;
+   if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
+   itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
+   if (it->rel)
+     {
+        it->rel->relcount--;
+        if ((it->rel->delete_me) && (!it->rel->relcount))
+          _item_del(it->rel);
+        it->rel = NULL;
+     }
+   if (itb->count > itb->wd->max_items_per_block)
+     {
+        int newc;
+        Item_Block *itb2;
+        Elm_Genlist_Item *it2;
+
+        newc = itb->count / 2;
+        itb2 = calloc(1, sizeof(Item_Block));
+        if (!itb2) return;
+        itb2->wd = wd;
+        wd->blocks =
+          eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
+                                      EINA_INLIST_GET(itb));
+        itb2->changed = EINA_TRUE;
+        while ((itb->count > newc) && (itb->items))
+          {
+             Eina_List *l;
+
+             l = eina_list_last(itb->items);
+             it2 = l->data;
+             itb->items = eina_list_remove_list(itb->items, l);
+             itb->count--;
+
+             itb2->items = eina_list_prepend(itb2->items, it2);
+             it2->block = itb2;
+             itb2->count++;
+          }
+     }
+}
+
+static int
+_queue_proecess(Widget_Data *wd,
+                int          norender)
+{
+   int n;
+   Eina_Bool showme = EINA_FALSE;
+   double t0, t;
+
+   t0 = ecore_time_get();
+   for (n = 0; (wd->queue) && (n < 128); n++)
+     {
+        Elm_Genlist_Item *it;
+
+        it = wd->queue->data;
+        wd->queue = eina_list_remove_list(wd->queue, wd->queue);
+        it->queued = EINA_FALSE;
+        _item_block_add(wd, it);
+        t = ecore_time_get();
+        if (it->block->changed)
+          {
+             showme = _item_block_recalc(it->block, it->block->num, 1,
+                                         norender);
+             it->block->changed = 0;
+          }
+        if (showme) it->block->showme = EINA_TRUE;
+        if (eina_inlist_count(wd->blocks) > 1)
+          {
+             if ((t - t0) > (ecore_animator_frametime_get())) break;
+          }
+     }
+   return n;
+}
+
+static Eina_Bool
+_item_idler(void *data)
+{
+   Widget_Data *wd = data;
+
+   //xxx
+   //static double q_start = 0.0;
+   //if (q_start == 0.0) q_start = ecore_time_get();
+   //xxx
+
+   if (_queue_proecess(wd, 1) > 0)
+     {
+        if (wd->calc_job) ecore_job_del(wd->calc_job);
+        wd->calc_job = ecore_job_add(_calc_job, wd);
+     }
+   if (!wd->queue)
+     {
+        //xxx
+        //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
+        //xxx
+        wd->queue_idler = NULL;
+        return ECORE_CALLBACK_CANCEL;
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_item_queue(Widget_Data      *wd,
+            Elm_Genlist_Item *it)
+{
+   if (it->queued) return;
+   it->queued = EINA_TRUE;
+   wd->queue = eina_list_append(wd->queue, it);
+   while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
+     {
+        if (wd->queue_idler)
+          {
+             ecore_idler_del(wd->queue_idler);
+             wd->queue_idler = NULL;
+          }
+        _queue_proecess(wd, 0);
+     }
+   if (!wd->queue_idler) wd->queue_idler = ecore_idler_add(_item_idler, wd);
+}
+
+/**
+ * Append item to the end of the genlist
+ *
+ * This appends the given item to the end of the list or the end of
+ * the children if the parent is given.
+ *
+ * @param obj The genlist object
+ * @param itc The item class for the item
+ * @param data The item data
+ * @param parent The parent item, or NULL if none
+ * @param flags Item flags
+ * @param func Convenience function called when item selected
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_item_append(Evas_Object                  *obj,
+                        const Elm_Genlist_Item_Class *itc,
+                        const void                   *data,
+                        Elm_Genlist_Item             *parent,
+                        Elm_Genlist_Item_Flags        flags,
+                        Evas_Smart_Cb                 func,
+                        const void                   *func_data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
+                                    func_data);
+   if (!wd) return NULL;
+   if (!it) return NULL;
+   if (!it->parent)
+     {
+        if (flags & ELM_GENLIST_ITEM_GROUP)
+           wd->group_items = eina_list_append(wd->group_items, it);
+        wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
+        it->rel = NULL;
+     }
+   else
+     {
+        Elm_Genlist_Item *it2 = NULL;
+        Eina_List *ll = eina_list_last(it->parent->items);
+        if (ll) it2 = ll->data;
+        it->parent->items = eina_list_append(it->parent->items, it);
+        if (!it2) it2 = it->parent;
+        wd->items =
+          eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
+                                      EINA_INLIST_GET(it2));
+        it->rel = it2;
+        it->rel->relcount++;
+
+        if (it->parent->flags & ELM_GENLIST_ITEM_GROUP) 
+           it->group_item = parent;
+        else if (it->parent->group_item)
+           it->group_item = it->parent->group_item;
+     }
+   it->before = EINA_FALSE;
+   _item_queue(wd, it);
+   return it;
+}
+
+/**
+ * Prepend item at start of the genlist
+ *
+ * This adds an item to the beginning of the list or beginning of the
+ * children of the parent if given.
+ *
+ * @param obj The genlist object
+ * @param itc The item class for the item
+ * @param data The item data
+ * @param parent The parent item, or NULL if none
+ * @param flags Item flags
+ * @param func Convenience function called when item selected
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_item_prepend(Evas_Object                  *obj,
+                         const Elm_Genlist_Item_Class *itc,
+                         const void                   *data,
+                         Elm_Genlist_Item             *parent,
+                         Elm_Genlist_Item_Flags        flags,
+                         Evas_Smart_Cb                 func,
+                         const void                   *func_data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
+                                    func_data);
+   if (!wd) return NULL;
+   if (!it) return NULL;
+   if (!it->parent)
+     {
+        if (flags & ELM_GENLIST_ITEM_GROUP)
+           wd->group_items = eina_list_prepend(wd->group_items, it);
+        wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
+        it->rel = NULL;
+     }
+   else
+     {
+        Elm_Genlist_Item *it2 = NULL;
+        Eina_List *ll = it->parent->items;
+        if (ll) it2 = ll->data;
+        it->parent->items = eina_list_prepend(it->parent->items, it);
+        if (!it2) it2 = it->parent;
+        wd->items =
+           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
+                                        EINA_INLIST_GET(it2));
+        it->rel = it2;
+        it->rel->relcount++;
+     }
+   it->before = EINA_TRUE;
+   _item_queue(wd, it);
+   return it;
+}
+
+/**
+ * Insert item before another in the genlist
+ *
+ * This inserts an item before another in the list. It will be in the
+ * same tree level or group as the item it is inseted before.
+ *
+ * @param obj The genlist object
+ * @param itc The item class for the item
+ * @param data The item data
+ * @param before The item to insert before
+ * @param flags Item flags
+ * @param func Convenience function called when item selected
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_item_insert_before(Evas_Object                  *obj,
+                               const Elm_Genlist_Item_Class *itc,
+                               const void                   *data,
+                               Elm_Genlist_Item             *parent,
+                               Elm_Genlist_Item             *before,
+                               Elm_Genlist_Item_Flags        flags,
+                               Evas_Smart_Cb                 func,
+                               const void                   *func_data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
+                                    func_data);
+   if (!wd) return NULL;
+   if (!it) return NULL;
+   if (it->parent)
+     {
+        it->parent->items = eina_list_prepend_relative(it->parent->items, it,
+                                                       before);
+     }
+   wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
+                                            EINA_INLIST_GET(before));
+   it->rel = before;
+   it->rel->relcount++;
+   it->before = EINA_TRUE;
+   _item_queue(wd, it);
+   return it;
+}
+
+/**
+ * Insert an item after another in the genlst
+ *
+ * This inserts an item after another in the list. It will be in the
+ * same tree level or group as the item it is inseted after.
+ *
+ * @param obj The genlist object
+ * @param itc The item class for the item
+ * @param data The item data
+ * @param after The item to insert after
+ * @param flags Item flags
+ * @param func Convenience function called when item selected
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the item added or NULL if not possible
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_item_insert_after(Evas_Object                  *obj,
+                              const Elm_Genlist_Item_Class *itc,
+                              const void                   *data,
+                              Elm_Genlist_Item             *parent,
+                              Elm_Genlist_Item             *after,
+                              Elm_Genlist_Item_Flags        flags,
+                              Evas_Smart_Cb                 func,
+                              const void                   *func_data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
+                                    func_data);
+   if (!wd) return NULL;
+   if (!it) return NULL;
+   wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
+                                           EINA_INLIST_GET(after));
+   if (it->parent)
+     {
+        it->parent->items = eina_list_append_relative(it->parent->items, it,
+                                                      after);
+     }
+   it->rel = after;
+   it->rel->relcount++;
+   it->before = EINA_FALSE;
+   _item_queue(wd, it);
+   return it;
+}
+
+/**
+ * Clear the genlist
+ *
+ * This clears all items in the list, leaving it empty.
+ *
+ * @param obj The genlist object
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->walking > 0)
+     {
+        Elm_Genlist_Item *it;
+
+        wd->clear_me = EINA_TRUE;
+        EINA_INLIST_FOREACH(wd->items, it)
+        {
+           it->delete_me = EINA_TRUE;
+        }
+        return;
+     }
+   wd->clear_me = EINA_FALSE;
+   while (wd->items)
+     {
+        Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
+
+        if (wd->anchor_item == it)
+          {
+             wd->anchor_item = (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->next);
+             if (!wd->anchor_item)
+               wd->anchor_item =
+                 (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->prev);
+          }
+        wd->items = eina_inlist_remove(wd->items, wd->items);
+        if (it->flags & ELM_GENLIST_ITEM_GROUP)
+          it->wd->group_items = eina_list_remove(it->wd->group_items, it);
+        elm_widget_item_pre_notify_del(it);
+        if (it->realized) _item_unrealize(it);
+        if (it->itc->func.del)
+          it->itc->func.del((void *)it->base.data, it->base.widget);
+        if (it->long_timer) ecore_timer_del(it->long_timer);
+        if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
+        elm_widget_item_del(it);
+     }
+   wd->anchor_item = NULL;
+   while (wd->blocks)
+     {
+        Item_Block *itb = (Item_Block *)(wd->blocks);
+
+        wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
+        if (itb->items) eina_list_free(itb->items);
+        free(itb);
+     }
+   if (wd->calc_job)
+     {
+        ecore_job_del(wd->calc_job);
+        wd->calc_job = NULL;
+     }
+   if (wd->queue_idler)
+     {
+        ecore_idler_del(wd->queue_idler);
+        wd->queue_idler = NULL;
+     }
+   if (wd->must_recalc_idler)
+     {
+        ecore_idler_del(wd->must_recalc_idler);
+        wd->must_recalc_idler = NULL;
+     }
+   if (wd->queue)
+     {
+        eina_list_free(wd->queue);
+        wd->queue = NULL;
+     }
+   if (wd->selected)
+     {
+        eina_list_free(wd->selected);
+        wd->selected = NULL;
+     }
+   wd->show_item = NULL;
+   wd->pan_x = 0;
+   wd->pan_y = 0;
+   wd->minw = 0;
+   wd->minh = 0;
+   if (wd->pan_smart)
+     {
+        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);
+}
+
+/**
+ * Enable or disable multi-select in the genlist
+ *
+ * This enables (EINA_TRUE) or disableds (EINA_FALSE) multi-select in
+ * the list. This allows more than 1 item to be selected.
+ *
+ * @param obj The genlist object
+ * @param multi Multi-select enable/disable
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_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;
+}
+
+/**
+ * Gets if multi-select in genlist is enable or disable
+ *
+ * @param obj The genlist object
+ * @return Multi-select enable/disable
+ * (EINA_TRUE = enabled/EINA_FALSE = disabled)
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_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 selectd item in the genlist
+ *
+ * This gets the selected item in the list (if multi-select is enabled
+ * only the first item in the list is selected - which is not very
+ * useful, so see elm_genlist_selected_items_get() for when
+ * multi-select is used).
+ *
+ * If no item is selected, NULL is returned.
+ *
+ * @param obj The genlist object
+ * @return The selected item, or NULL if none.
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_selected_item_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 items in the genlist
+ *
+ * This returns a list of the selected items. This list pointer is
+ * only valid so long as no items are selected or unselected (or
+ * unselected implicitly by deletion). The list contains
+ * Elm_Genlist_Item pointers.
+ *
+ * @param obj The genlist object
+ * @return The list of selected items, nor NULL if none are selected.
+ *
+ * @ingroup Genlist
+ */
+EAPI const Eina_List *
+elm_genlist_selected_items_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 a list of realized items in genlist
+ *
+ * This returns a list of the realized items in the genlist. The list
+ * contains Elm_Genlist_Item pointers. The list must be freed by the
+ * caller when done with eina_list_free(). The item pointers in the
+ * list are only valid so long as those items are not deleted or the
+ * genlist is not deleted.
+ *
+ * @param obj The genlist object
+ * @return The list of realized items, nor NULL if none are realized.
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_List *
+elm_genlist_realized_items_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *list = NULL;
+   Item_Block *itb;
+   Eina_Bool done = EINA_FALSE;
+   if (!wd) return NULL;
+   EINA_INLIST_FOREACH(wd->blocks, itb)
+   {
+      if (itb->realized)
+        {
+           Eina_List *l;
+           Elm_Genlist_Item *it;
+
+           done = 1;
+           EINA_LIST_FOREACH(itb->items, l, it)
+             {
+                if (it->realized) list = eina_list_append(list, it);
+             }
+        }
+      else
+        {
+           if (done) break;
+        }
+   }
+   return list;
+}
+
+/**
+ * Get the item that is at the x, y canvas coords
+ *
+ * This returns the item at the given coordinates (which are canvas
+ * relative not object-relative). If an item is at that coordinate,
+ * that item handle is returned, and if @p posret is not NULL, the
+ * integer pointed to is set to a value of -1, 0 or 1, depending if
+ * the coordinate is on the upper portion of that item (-1), on the
+ * middle section (0) or on the lower part (1). If NULL is returned as
+ * an item (no item found there), then posret may indicate -1 or 1
+ * based if the coordinate is above or below all items respectively in
+ * the genlist.
+ *
+ * @param it The item
+ * @param x The input x coordinate
+ * @param y The input y coordinate
+ * @param posret The position relative to the item returned here
+ * @return The item at the coordinates or NULL if none
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_at_xy_item_get(const Evas_Object *obj,
+                           Evas_Coord         x,
+                           Evas_Coord         y,
+                           int               *posret)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord ox, oy, ow, oh;
+   Item_Block *itb;
+   Evas_Coord lasty;
+   if (!wd) return NULL;
+   evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
+   lasty = oy;
+   EINA_INLIST_FOREACH(wd->blocks, itb)
+   {
+      Eina_List *l;
+      Elm_Genlist_Item *it;
+
+      if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
+                               oy + itb->y - itb->wd->pan_y,
+                               itb->w, itb->h, x, y, 1, 1))
+        continue;
+      EINA_LIST_FOREACH(itb->items, l, it)
+        {
+           Evas_Coord itx, ity;
+
+           itx = ox + itb->x + it->x - itb->wd->pan_x;
+           ity = oy + itb->y + it->y - itb->wd->pan_y;
+           if (ELM_RECTS_INTERSECT(itx, ity, it->w, it->h, x, y, 1, 1))
+             {
+                if (posret)
+                  {
+                     if (y <= (ity + (it->h / 4))) *posret = -1;
+                     else if (y >= (ity + it->h - (it->h / 4)))
+                       *posret = 1;
+                     else *posret = 0;
+                  }
+                return it;
+             }
+           lasty = ity + it->h;
+        }
+   }
+   if (posret)
+     {
+        if (y > lasty) *posret = 1;
+        else *posret = -1;
+     }
+   return NULL;
+}
+
+/**
+ * Get the first item in the genlist
+ *
+ * This returns the first item in the list.
+ *
+ * @param obj The genlist object
+ * @return The first item, or NULL if none
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_first_item_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->items) return NULL;
+   Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
+   while ((it) && (it->delete_me))
+     it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
+   return it;
+}
+
+/**
+ * Get the last item in the genlist
+ *
+ * This returns the last item in the list.
+ *
+ * @return The last item, or NULL if none
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_last_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd->items) return NULL;
+   Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items->last);
+   if (!wd) return NULL;
+   while ((it) && (it->delete_me))
+     it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
+   return it;
+}
+
+/**
+ * Get the next item in the genlist
+ *
+ * This returns the item after the item @p it.
+ *
+ * @param it The item
+ * @return The item after @p it, or NULL if none
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_item_next_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   while (it)
+     {
+        it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
+        if ((it) && (!it->delete_me)) break;
+     }
+   return (Elm_Genlist_Item *)it;
+}
+
+/**
+ * Get the previous item in the genlist
+ *
+ * This returns the item before the item @p it.
+ *
+ * @param it The item
+ * @return The item before @p it, or NULL if none
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_item_prev_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   while (it)
+     {
+        it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
+        if ((it) && (!it->delete_me)) break;
+     }
+   return (Elm_Genlist_Item *)it;
+}
+
+/**
+ * Get the genlist object from an item
+ *
+ * This returns the genlist object itself that an item belongs to.
+ *
+ * @param it The item
+ * @return The genlist object
+ *
+ * @ingroup Genlist
+ */
+EAPI Evas_Object *
+elm_genlist_item_genlist_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   return it->base.widget;
+}
+
+/**
+ * Get the parent item of the given item
+ *
+ * This returns the parent item of the item @p it given.
+ *
+ * @param it The item
+ * @return The parent of the item or NULL if none
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_Genlist_Item *
+elm_genlist_item_parent_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   return it->parent;
+}
+
+/**
+ * Clear all sub-items (children) of the given item
+ *
+ * This clears all items that are children (or their descendants) of the
+ * given item @p it.
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_subitems_clear(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Eina_List *tl = NULL, *l;
+   Elm_Genlist_Item *it2;
+
+   EINA_LIST_FOREACH(it->items, l, it2)
+     tl = eina_list_append(tl, it2);
+   EINA_LIST_FREE(tl, it2)
+     elm_genlist_item_del(it2);
+}
+
+/**
+ * Set the selected state of an item
+ *
+ * This sets the selected state (1 selected, 0 not selected) of the given
+ * item @p it.
+ *
+ * @param it The item
+ * @param selected The selected state
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_selected_set(Elm_Genlist_Item *it,
+                              Eina_Bool         selected)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   if (!wd) return;
+   if (it->delete_me) return;
+   selected = !!selected;
+   if (it->selected == selected) return;
+
+   if (selected)
+     {
+        if (!wd->multi)
+          {
+             while (wd->selected)
+               _item_unselect(wd->selected->data);
+          }
+        _item_hilight(it);
+        _item_select(it);
+     }
+   else
+     _item_unselect(it);
+}
+
+/**
+ * Get the selected state of an item
+ *
+ * This gets the selected state of an item (1 selected, 0 not selected).
+ *
+ * @param it The item
+ * @return The selected state
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_item_selected_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
+   return it->selected;
+}
+
+/**
+ * Sets the expanded state of an item (if it's a parent)
+ *
+ * This expands or contracts a parent item (thus showing or hiding the
+ * children).
+ *
+ * @param it The item
+ * @param expanded The expanded state (1 expanded, 0 not expanded).
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_expanded_set(Elm_Genlist_Item *it,
+                              Eina_Bool         expanded)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   if (it->expanded == expanded) return;
+   it->expanded = expanded;
+   if (it->expanded)
+     {
+        if (it->realized)
+          edje_object_signal_emit(it->base.view, "elm,state,expanded", "elm");
+        evas_object_smart_callback_call(it->base.widget, "expanded", it);
+     }
+   else
+     {
+        if (it->realized)
+          edje_object_signal_emit(it->base.view, "elm,state,contracted", "elm");
+        evas_object_smart_callback_call(it->base.widget, "contracted", it);
+     }
+}
+
+/**
+ * Get the expanded state of an item
+ *
+ * This gets the expanded state of an item
+ *
+ * @param it The item
+ * @return Thre expanded state
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_item_expanded_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
+   return it->expanded;
+}
+
+/**
+ * Get the depth of expanded item
+ *
+ * @param it The genlist item object
+ * @return The depth of expanded item
+ *
+ * @ingroup Genlist
+ */
+EAPI int
+elm_genlist_item_expanded_depth_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, 0);
+   return it->expanded_depth;
+}
+
+/**
+ * Sets the disabled state of an item.
+ *
+ * A disabled item cannot be selected or unselected. It will also
+ * change appearance to appear disabled. This sets the disabled state
+ * (1 disabled, 0 not disabled).
+ *
+ * @param it The item
+ * @param disabled The disabled state
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_disabled_set(Elm_Genlist_Item *it,
+                              Eina_Bool         disabled)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   if (it->disabled == disabled) return;
+   if (it->delete_me) return;
+   it->disabled = disabled;
+   if (it->realized)
+     {
+        if (it->disabled)
+          edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
+        else
+          edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
+     }
+}
+
+/**
+ * Get the disabled state of an item
+ *
+ * This gets the disabled state of the given item.
+ *
+ * @param it The item
+ * @return The disabled state
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_item_disabled_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
+   if (it->delete_me) return EINA_FALSE;
+   return it->disabled;
+}
+
+/**
+ * Sets the display only state of an item.
+ *
+ * A display only item cannot be selected or unselected. It is for
+ * display only and not selecting or otherwise clicking, dragging
+ * etc. by the user, thus finger size rules will not be applied to
+ * this item.
+ *
+ * @param it The item
+ * @param display_only The display only state
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_display_only_set(Elm_Genlist_Item *it,
+                                  Eina_Bool         display_only)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   if (!it->block) return;
+   if (it->display_only == display_only) return;
+   if (it->delete_me) return;
+   it->display_only = display_only;
+   it->mincalcd = EINA_FALSE;
+   it->updateme = EINA_TRUE;
+   it->block->updateme = EINA_TRUE;
+   if (it->wd->update_job) ecore_job_del(it->wd->update_job);
+   it->wd->update_job = ecore_job_add(_update_job, it->wd);
+}
+
+/**
+ * Get the display only state of an item
+ *
+ * This gets the display only state of the given item.
+ *
+ * @param it The item
+ * @return The display only state
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_item_display_only_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
+   if (it->delete_me) return EINA_FALSE;
+   return it->display_only;
+}
+
+/**
+ * Show the given item
+ *
+ * This causes genlist to jump to the given item @p it and show it (by
+ * scrolling), if it is not fully visible.
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_show(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Evas_Coord gith = 0;
+   if (it->delete_me) return;
+   if ((it->queued) || (!it->mincalcd))
+     {
+        it->wd->show_item = it;
+        it->wd->bring_in = EINA_TRUE;
+        it->showme = EINA_TRUE;
+        return;
+     }
+   if (it->wd->show_item)
+     {
+        it->wd->show_item->showme = EINA_FALSE;
+        it->wd->show_item = NULL;
+     }
+   if ((it->group_item) && (it->wd->pan_y > (it->y + it->block->y)))
+      gith = it->group_item->h;
+   elm_smart_scroller_child_region_show(it->wd->scr,
+                                        it->x + it->block->x,
+                                        it->y + it->block->y - gith,
+                                        it->block->w, it->h);
+}
+
+/**
+ * Bring in the given item
+ *
+ * This causes genlist to jump to the given item @p it and show it (by
+ * scrolling), if it is not fully visible. This may use animation to
+ * do so and take a period of time
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_bring_in(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Evas_Coord gith = 0; 
+   if (it->delete_me) return;
+   if ((it->queued) || (!it->mincalcd))
+     {
+        it->wd->show_item = it;
+        it->wd->bring_in = EINA_TRUE;
+        it->showme = EINA_TRUE;
+        return;
+     }
+   if (it->wd->show_item)
+     {
+        it->wd->show_item->showme = EINA_FALSE;
+        it->wd->show_item = NULL;
+     }
+   if ((it->group_item) && (it->wd->pan_y > (it->y + it->block->y)))
+      gith = it->group_item->h;
+   elm_smart_scroller_region_bring_in(it->wd->scr,
+                                      it->x + it->block->x,
+                                      it->y + it->block->y - gith,
+                                      it->block->w, it->h);
+}
+
+/**
+ * Show the given item at the top
+ *
+ * This causes genlist to jump to the given item @p it and show it (by
+ * scrolling), if it is not fully visible.
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_top_show(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Evas_Coord ow, oh;
+   Evas_Coord gith = 0;
+
+   if (it->delete_me) return;
+   if ((it->queued) || (!it->mincalcd))
+     {
+        it->wd->show_item = it;
+        it->wd->bring_in = EINA_TRUE;
+        it->showme = EINA_TRUE;
+        return;
+     }
+   if (it->wd->show_item)
+     {
+        it->wd->show_item->showme = EINA_FALSE;
+        it->wd->show_item = NULL;
+     }
+   evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
+   if (it->group_item) gith = it->group_item->h;
+   elm_smart_scroller_child_region_show(it->wd->scr,
+                                        it->x + it->block->x,
+                                        it->y + it->block->y - gith,
+                                        it->block->w, oh);
+}
+
+/**
+ * Bring in the given item at the top
+ *
+ * This causes genlist to jump to the given item @p it and show it (by
+ * scrolling), if it is not fully visible. This may use animation to
+ * do so and take a period of time
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_top_bring_in(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Evas_Coord ow, oh;
+   Evas_Coord gith = 0;
+
+   if (it->delete_me) return;
+   if ((it->queued) || (!it->mincalcd))
+     {
+        it->wd->show_item = it;
+        it->wd->bring_in = EINA_TRUE;
+        it->showme = EINA_TRUE;
+        return;
+     }
+   if (it->wd->show_item)
+     {
+        it->wd->show_item->showme = EINA_FALSE;
+        it->wd->show_item = NULL;
+     }
+   evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
+   if (it->group_item) gith = it->group_item->h;
+   elm_smart_scroller_region_bring_in(it->wd->scr,
+                                      it->x + it->block->x,
+                                      it->y + it->block->y - gith,
+                                      it->block->w, oh);
+}
+
+/**
+ * Show the given item at the middle
+ *
+ * This causes genlist to jump to the given item @p it and show it (by
+ * scrolling), if it is not fully visible.
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_middle_show(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Evas_Coord ow, oh;
+
+   if (it->delete_me) return;
+   if ((it->queued) || (!it->mincalcd))
+     {
+        it->wd->show_item = it;
+        it->wd->bring_in = EINA_TRUE;
+        it->showme = EINA_TRUE;
+        return;
+     }
+   if (it->wd->show_item)
+     {
+        it->wd->show_item->showme = EINA_FALSE;
+        it->wd->show_item = NULL;
+     }
+   evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
+   elm_smart_scroller_child_region_show(it->wd->scr,
+                                        it->x + it->block->x,
+                                        it->y + it->block->y - oh / 2 +
+                                        it->h / 2, it->block->w, oh);
+}
+
+/**
+ * Bring in the given item at the middle
+ *
+ * This causes genlist to jump to the given item @p it and show it (by
+ * scrolling), if it is not fully visible. This may use animation to
+ * do so and take a period of time
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_middle_bring_in(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   Evas_Coord ow, oh;
+
+   if (it->delete_me) return;
+   if ((it->queued) || (!it->mincalcd))
+     {
+        it->wd->show_item = it;
+        it->wd->bring_in = EINA_TRUE;
+        it->showme = EINA_TRUE;
+        return;
+     }
+   if (it->wd->show_item)
+     {
+        it->wd->show_item->showme = EINA_FALSE;
+        it->wd->show_item = NULL;
+     }
+   evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
+   elm_smart_scroller_region_bring_in(it->wd->scr,
+                                      it->x + it->block->x,
+                                      it->y + it->block->y - oh / 2 + it->h / 2,
+                                      it->block->w, oh);
+}
+
+/**
+ * Delete a given item
+ *
+ * This deletes the item from genlist and calls the genlist item del
+ * class callback defined in the item class, if it is set. This clears all
+ * subitems if it is a tree.
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_del(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   if ((it->relcount > 0) || (it->walking > 0))
+     {
+        elm_widget_item_pre_notify_del(it);
+        elm_genlist_item_subitems_clear(it);
+        it->delete_me = EINA_TRUE;
+        if (it->wd->show_item == it) it->wd->show_item = NULL;
+        if (it->selected)
+          it->wd->selected = eina_list_remove(it->wd->selected,
+                                              it);
+        if (it->block)
+          {
+             if (it->realized) _item_unrealize(it);
+             it->block->changed = EINA_TRUE;
+             if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
+             it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
+          }
+        if (it->itc->func.del)
+          it->itc->func.del((void *)it->base.data, it->base.widget);
+        return;
+     }
+   _item_del(it);
+}
+
+/**
+ * Set the data item from the genlist item
+ *
+ * This set the data value passed on the elm_genlist_item_append() and
+ * related item addition calls. This function will also call
+ * elm_genlist_item_update() so the item will be updated to reflect the
+ * new data.
+ *
+ * @param it The item
+ * @param data The new data pointer to set
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_data_set(Elm_Genlist_Item *it,
+                          const void       *data)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   elm_widget_item_data_set(it, data);
+   elm_genlist_item_update(it);
+}
+
+/**
+ * Get the data item from the genlist item
+ *
+ * This returns the data value passed on the elm_genlist_item_append()
+ * and related item addition calls and elm_genlist_item_data_set().
+ *
+ * @param it The item
+ * @return The data pointer provided when created
+ *
+ * @ingroup Genlist
+ */
+EAPI void *
+elm_genlist_item_data_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   return elm_widget_item_data_get(it);
+}
+
+/**
+ * Tells genlist to "orphan" icons fetchs by the item class
+ *
+ * This instructs genlist to release references to icons in the item,
+ * meaning that they will no longer be managed by genlist and are
+ * floating "orphans" that can be re-used elsewhere if the user wants
+ * to.
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_icons_orphan(Elm_Genlist_Item *it)
+{
+   Evas_Object *icon;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   EINA_LIST_FREE(it->icon_objs, icon)
+     {
+        elm_widget_sub_object_del(it->base.widget, icon);
+        evas_object_smart_member_del(icon);
+        evas_object_hide(icon);
+     }
+}
+
+/**
+ * Get the real evas object of the genlist item
+ *
+ * This returns the actual evas object used for the specified genlist
+ * item. This may be NULL as it may not be created, and may be deleted
+ * at any time by genlist. Do not modify this object (move, resize,
+ * show, hide etc.) as genlist 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 it The item
+ * @return The object pointer
+ *
+ * @ingroup Genlist
+ */
+EAPI const Evas_Object *
+elm_genlist_item_object_get(const Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   return it->base.view;
+}
+
+/**
+ * Update the contents of an item
+ *
+ * This updates an item by calling all the item class functions again
+ * to get the icons, labels and states. Use this when the original
+ * item data has changed and the changes are desired to be reflected.
+ *
+ * @param it The item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_update(Elm_Genlist_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   if (!it->block) return;
+   if (it->delete_me) return;
+   it->mincalcd = EINA_FALSE;
+   it->updateme = EINA_TRUE;
+   it->block->updateme = EINA_TRUE;
+   if (it->wd->update_job) ecore_job_del(it->wd->update_job);
+   it->wd->update_job = ecore_job_add(_update_job, it->wd);
+}
+
+/**
+ * Update the item class of an item
+ *
+ * @param it The item
+ * @parem itc The item class for the item
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_item_class_update(Elm_Genlist_Item             *it,
+                                   const Elm_Genlist_Item_Class *itc)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   if (!it->block) return;
+   EINA_SAFETY_ON_NULL_RETURN(itc);
+   if (it->delete_me) return;
+   it->itc = itc;
+   elm_genlist_item_update(it);
+}
+
+static Evas_Object *
+_elm_genlist_item_label_create(void        *data,
+                               Evas_Object *obj,
+                               void *item   __UNUSED__)
+{
+   Evas_Object *label = elm_label_add(obj);
+   if (!label)
+     return NULL;
+   elm_object_style_set(label, "tooltip");
+   elm_label_label_set(label, data);
+   return label;
+}
+
+static void
+_elm_genlist_item_label_del_cb(void            *data,
+                               Evas_Object *obj __UNUSED__,
+                               void *event_info __UNUSED__)
+{
+   eina_stringshare_del(data);
+}
+
+/**
+ * Set the text to be shown in the genlist item.
+ *
+ * @param item Target item
+ * @param text The text to set in the content
+ *
+ * Setup the text as tooltip to object. The item can have only one
+ * tooltip, so any previous tooltip data is removed.
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_tooltip_text_set(Elm_Genlist_Item *item,
+                                  const char       *text)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   text = eina_stringshare_add(text);
+   elm_genlist_item_tooltip_content_cb_set(item, _elm_genlist_item_label_create,
+                                           text,
+                                           _elm_genlist_item_label_del_cb);
+}
+
+/**
+ * Set the content to be shown in the tooltip item
+ *
+ * Setup the tooltip to item. The item can have only one tooltip, so
+ * any previous tooltip data is removed. @p func(with @p data) will be
+ * called every time that need to show the tooltip and it should return a
+ * valid Evas_Object. This object is then managed fully by tooltip
+ * system and is deleted when the tooltip is gone.
+ *
+ * @param item the genlist item being attached by a tooltip.
+ * @param func the function used to create the tooltip contents.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_genlist_item_tooltip_unset() or the owner @a item
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is the item.
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_tooltip_content_cb_set(Elm_Genlist_Item           *item,
+                                        Elm_Tooltip_Item_Content_Cb func,
+                                        const void                 *data,
+                                        Evas_Smart_Cb               del_cb)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(item, error);
+
+   if ((item->tooltip.content_cb == func) && (item->tooltip.data == data))
+     return;
+
+   if (item->tooltip.del_cb)
+     item->tooltip.del_cb((void *)item->tooltip.data,
+                          item->base.widget, item);
+
+   item->tooltip.content_cb = func;
+   item->tooltip.data = data;
+   item->tooltip.del_cb = del_cb;
+
+   if (item->base.view)
+     {
+        elm_widget_item_tooltip_content_cb_set(item,
+                                               item->tooltip.content_cb,
+                                               item->tooltip.data, NULL);
+        elm_widget_item_tooltip_style_set(item, item->tooltip.style);
+     }
+
+   return;
+
+error:
+   if (del_cb) del_cb((void *)data, NULL, NULL);
+}
+
+/**
+ * Unset tooltip from item
+ *
+ * @param item genlist item to remove previously set tooltip.
+ *
+ * Remove tooltip from item. The callback provided as del_cb to
+ * elm_genlist_item_tooltip_content_cb_set() will be called to notify
+ * it is not used anymore.
+ *
+ * @see elm_genlist_item_tooltip_content_cb_set()
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_tooltip_unset(Elm_Genlist_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if ((item->base.view) && (item->tooltip.content_cb))
+     elm_widget_item_tooltip_unset(item);
+
+   if (item->tooltip.del_cb)
+     item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
+   item->tooltip.del_cb = NULL;
+   item->tooltip.content_cb = NULL;
+   item->tooltip.data = NULL;
+   if (item->tooltip.style)
+     elm_genlist_item_tooltip_style_set(item, NULL);
+}
+
+/**
+ * Sets a different style for this item tooltip.
+ *
+ * @note before you set a style you should define a tooltip with
+ *       elm_genlist_item_tooltip_content_cb_set() or
+ *       elm_genlist_item_tooltip_text_set()
+ *
+ * @param item genlist item with tooltip already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_tooltip_style_set(Elm_Genlist_Item *item,
+                                   const char       *style)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   eina_stringshare_replace(&item->tooltip.style, style);
+   if (item->base.view) elm_widget_item_tooltip_style_set(item, style);
+}
+
+/**
+ * Get the style for this item tooltip.
+ *
+ * @param item genlist item with tooltip already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a tooltip set, then NULL is returned.
+ *
+ * @ingroup Genlist
+ */
+EAPI const char *
+elm_genlist_item_tooltip_style_get(const Elm_Genlist_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->tooltip.style;
+}
+
+/**
+ * Set the cursor to be shown when mouse is over the genlist item
+ *
+ * @param item Target item
+ * @param cursor the cursor name to be used.
+ *
+ * @see elm_object_cursor_set()
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_cursor_set(Elm_Genlist_Item *item,
+                            const char       *cursor)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   eina_stringshare_replace(&item->mouse_cursor, cursor);
+   if (item->base.view) elm_widget_item_cursor_set(item, cursor);
+}
+
+/**
+ * Get the cursor to be shown when mouse is over the genlist item
+ *
+ * @param item genlist item with cursor already set.
+ * @return the cursor name.
+ *
+ * @ingroup Genlist
+ */
+EAPI const char *
+elm_genlist_item_cursor_get(const Elm_Genlist_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_get(item);
+}
+
+/**
+ * Unset the cursor to be shown when mouse is over the genlist item
+ *
+ * @param item Target item
+ *
+ * @see elm_object_cursor_unset()
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_cursor_unset(Elm_Genlist_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (!item->mouse_cursor)
+     return;
+
+   if (item->base.view)
+     elm_widget_item_cursor_unset(item);
+
+   eina_stringshare_del(item->mouse_cursor);
+   item->mouse_cursor = NULL;
+}
+
+/**
+ * Sets a different style for this item cursor.
+ *
+ * @note before you set a style you should define a cursor with
+ *       elm_genlist_item_cursor_set()
+ *
+ * @param item genlist item with cursor already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_cursor_style_set(Elm_Genlist_Item *item,
+                                  const char       *style)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_style_set(item, style);
+}
+
+/**
+ * Get the style for this item cursor.
+ *
+ * @param item genlist item with cursor already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup Genlist
+ */
+EAPI const char *
+elm_genlist_item_cursor_style_get(const Elm_Genlist_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_style_get(item);
+}
+
+/**
+ * Set if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a
+ * cursor with elm_object_cursor_set(). By default it will only look
+ * for cursors provided by the engine.
+ *
+ * @param item widget item with cursor already set.
+ * @param engine_only boolean to define it cursors should be looked
+ * only between the provided by the engine or searched on widget's
+ * theme as well.
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_item_cursor_engine_only_set(Elm_Genlist_Item *item,
+                                        Eina_Bool         engine_only)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_engine_only_set(item, engine_only);
+}
+
+/**
+ * Get the cursor engine only usage for this item cursor.
+ *
+ * @param item widget item with cursor already set.
+ * @return engine_only boolean to define it cursors should be looked
+ * only between the provided by the engine or searched on widget's
+ * theme as well. If the object does not have a cursor set, then
+ * EINA_FALSE is returned.
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_item_cursor_engine_only_get(const Elm_Genlist_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return elm_widget_item_cursor_engine_only_get(item);
+}
+
+/**
+ * This sets the horizontal stretching mode
+ *
+ * This sets the mode used for sizing items horizontally. Valid modes
+ * are ELM_LIST_LIMIT and ELM_LIST_SCROLL. The default is
+ * ELM_LIST_SCROLL. This mode means that if items are too wide to fit,
+ * the scroller will scroll horizontally. Otherwise items are expanded
+ * to fill the width of the viewport of the scroller. If it is
+ * ELM_LIST_LIMIT, Items will be expanded to the viewport width and
+ * limited to that size.
+ *
+ * @param obj The genlist object
+ * @param mode The mode to use
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_horizontal_mode_set(Evas_Object  *obj,
+                                Elm_List_Mode mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->mode == mode) return;
+   wd->mode = mode;
+   _sizing_eval(obj);
+}
+
+/**
+ * Gets the horizontal stretching mode
+ *
+ * @param obj The genlist object
+ * @return The mode to use
+ * (ELM_LIST_LIMIT, ELM_LIST_SCROLL)
+ *
+ * @ingroup Genlist
+ */
+EAPI Elm_List_Mode
+elm_genlist_horizontal_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_LIST_LAST;
+   return wd->mode;
+}
+
+/**
+ * Set the always select mode.
+ *
+ * Items 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_genlist_always_select_mode_set().
+ * This means even if selected, every click will make the selected
+ * callbacks be called.
+ *
+ * @param obj The genlist object
+ * @param always_select The always select mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_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 genlist object
+ * @return The always select mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_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 genlist object
+ * @param no_select The no select mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_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 genlist object
+ * @return The no select mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_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 compress mode
+ *
+ * This will enable the compress mode where items are "compressed"
+ * horizontally to fit the genlist scrollable viewport width. This is
+ * special for genlist.  Do not rely on
+ * elm_genlist_horizontal_mode_set() being set to ELM_LIST_COMPRESS to
+ * work as genlist needs to handle it specially.
+ *
+ * @param obj The genlist object
+ * @param compress The compress mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_compress_mode_set(Evas_Object *obj,
+                              Eina_Bool    compress)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->compress = compress;
+}
+
+/**
+ * Get the compress mode
+ *
+ * @param obj The genlist object
+ * @return The compress mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_compress_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->compress;
+}
+
+/**
+ * Set height-for-width mode
+ *
+ * With height-for-width mode the item width will be fixed (restricted
+ * to a minimum of) to the list width when calculating its size in
+ * order to allow the height to be calculated based on it. This allows,
+ * for instance, text block to wrap lines if the Edje part is
+ * configured with "text.min: 0 1".
+ *
+ * @note This mode will make list resize slower as it will have to
+ *       recalculate every item height again whenever the list width
+ *       changes!
+ *
+ * @note When height-for-width mode is enabled, it also enables
+ *       compress mode (see elm_genlist_compress_mode_set()) and
+ *       disables homogeneous (see elm_genlist_homogeneous_set()).
+ *
+ * @param obj The genlist object
+ * @param setting The height-for-width mode (EINA_TRUE = on,
+ * EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_height_for_width_mode_set(Evas_Object *obj,
+                                      Eina_Bool    height_for_width)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->height_for_width = !!height_for_width;
+   if (wd->height_for_width)
+     {
+        elm_genlist_homogeneous_set(obj, EINA_FALSE);
+        elm_genlist_compress_mode_set(obj, EINA_TRUE);
+     }
+}
+
+/**
+ * Get the height-for-width mode
+ *
+ * @param obj The genlist object
+ * @return The height-for-width mode (EINA_TRUE = on, EINA_FALSE =
+ * off)
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_height_for_width_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->height_for_width;
+}
+
+/**
+ * Set bounce mode
+ *
+ * This will enable or disable the scroller bounce mode for the
+ * genlist. See elm_scroller_bounce_set() for details
+ *
+ * @param obj The genlist object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_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 genlist object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_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(obj, h_bounce, v_bounce);
+}
+
+/**
+ * Set homogenous mode
+ *
+ * This will enable the homogeneous mode where items are of the same
+ * height and width so that genlist may do the lazy-loading at its
+ * maximum. This implies 'compressed' mode.
+ *
+ * @param obj The genlist object
+ * @param homogeneous Assume the items within the genlist are of the
+ * same height and width (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_homogeneous_set(Evas_Object *obj,
+                            Eina_Bool    homogeneous)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
+   wd->homogeneous = homogeneous;
+}
+
+/**
+ * Get the homogenous mode
+ *
+ * @param obj The genlist object
+ * @return Assume the items within the genlist are of the same height
+ * and width (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_homogeneous_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->homogeneous;
+}
+
+/**
+ * Set the maximum number of items within an item block
+ *
+ * This will configure the block count to tune to the target with
+ * particular performance matrix.
+ *
+ * @param obj The genlist object
+ * @param n   Maximum number of items within an item block
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_block_count_set(Evas_Object *obj,
+                            int          n)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->max_items_per_block = n;
+   wd->item_cache_max = wd->max_items_per_block * 2;
+   _item_cache_clean(wd);
+}
+
+/**
+ * Get the maximum number of items within an item block
+ *
+ * @param obj The genlist object
+ * @return Maximum number of items within an item block
+ *
+ * @ingroup Genlist
+ */
+EAPI int
+elm_genlist_block_count_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->max_items_per_block;
+}
+
+/**
+ * Set the timeout in seconds for the longpress event
+ *
+ * @param obj The genlist object
+ * @param timeout timeout in seconds
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_longpress_timeout_set(Evas_Object *obj,
+                                  double       timeout)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->longpress_timeout = timeout;
+}
+
+/**
+ * Get the timeout in seconds for the longpress event
+ *
+ * @param obj The genlist object
+ * @return timeout in seconds
+ *
+ * @ingroup Genlist
+ */
+EAPI double
+elm_genlist_longpress_timeout_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->longpress_timeout;
+}
+
+/**
+ * Set the scrollbar policy
+ *
+ * This sets the scrollbar visibility policy for the given genlist
+ * scroller. ELM_SMART_SCROLLER_POLICY_AUTO means the scrollbar 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 genlist object
+ * @param policy_h Horizontal scrollbar policy
+ * @param policy_v Vertical scrollbar policy
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_scroller_policy_set(Evas_Object        *obj,
+                                Elm_Scroller_Policy policy_h,
+                                Elm_Scroller_Policy policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
+       (policy_v >= ELM_SCROLLER_POLICY_LAST))
+     return;
+   if (wd->scr)
+     elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
+}
+
+/**
+ * Get the scrollbar policy
+ *
+ * @param obj The genlist object
+ * @param policy_h Horizontal scrollbar policy
+ * @param policy_v Vertical scrollbar policy
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_scroller_policy_get(const Evas_Object   *obj,
+                                Elm_Scroller_Policy *policy_h,
+                                Elm_Scroller_Policy *policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
+   if ((!wd) || (!wd->scr)) return;
+   elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
+   if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
+   if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
+}
diff --git a/src/lib/elm_hover.c b/src/lib/elm_hover.c
new file mode 100644 (file)
index 0000000..45d5447
--- /dev/null
@@ -0,0 +1,957 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Hover Hover
+ *
+ * A Hover object will over its @p parent object at the @p target
+ * location. Anything in the background will be given a darker
+ * coloring to indicate that the hover object is on top (at the
+ * default theme).
+ *
+ * @note The hover object will take up the entire space of @p target
+ * object.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Content_Info Content_Info;
+
+#ifndef MAX
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define ELM_HOVER_PARTS_FOREACH unsigned int i = 0; \
+  for (i = 0; i < sizeof(wd->subs) / sizeof(wd->subs[0]); i++)
+
+static const char *_directions[] = {
+  "left",
+  "top-left",
+  "top",
+  "top-right",
+  "right",
+  "bottom-right",
+  "bottom",
+  "bottom-left",
+  "middle"
+};
+
+#define _HOV_LEFT (_directions[0])
+#define _HOV_TOP_LEFT (_directions[1])
+#define _HOV_TOP (_directions[2])
+#define _HOV_TOP_RIGHT (_directions[2])
+#define _HOV_RIGHT (_directions[4])
+#define _HOV_BOTTOM_RIGHT (_directions[5])
+#define _HOV_BOTTOM (_directions[6])
+#define _HOV_BOTTOM_LEFT (_directions[7])
+#define _HOV_MIDDLE (_directions[8])
+
+struct _Content_Info
+{
+   const char *swallow;
+   Evas_Object *obj;
+};
+
+struct _Widget_Data
+{
+   Evas_Object *hov, *cov;
+   Evas_Object *offset, *size;
+   Evas_Object *parent, *target;
+   Evas_Object *smt_sub;
+   Content_Info subs[sizeof(_directions)/sizeof(_directions[0])];
+};
+
+static const char *widtype = NULL;
+static void _del_pre_hook(Evas_Object *obj);
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _reval_content(Evas_Object *obj);
+static void _sub_del(void *data, Evas_Object *obj, void *event_info);
+static void _hov_show_do(Evas_Object *obj);
+static void _hov_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _hov_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _hov_show(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _hov_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _elm_hover_sub_obj_placement_eval_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _elm_hover_sub_obj_placement_eval(Evas_Object *obj);
+
+static const char SIG_CLICKED[] = "clicked";
+static const char SIG_SMART_LOCATION_CHANGED[] = "smart,changed";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CLICKED, ""},
+  {SIG_SMART_LOCATION_CHANGED, ""},
+  {NULL, NULL}
+};
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (evas_object_visible_get(obj))
+     evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
+   elm_hover_target_set(obj, NULL);
+   elm_hover_parent_set(obj, NULL);
+   evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_MOVE, _hov_move, obj);
+   evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_RESIZE, _hov_resize, obj);
+   evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_SHOW, _hov_show, obj);
+   evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_HIDE, _hov_hide, obj);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   free(wd);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->cov, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->cov, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->cov, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->cov, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   // FIXME: hover contents doesn't seem to propagate resizes properly
+   _elm_theme_object_set(obj, wd->cov, "hover", "base", elm_widget_style_get(obj));
+   edje_object_scale_set(wd->cov, elm_widget_scale_get(obj) *
+                         _elm_config->scale);
+
+   if (wd->smt_sub)
+      _elm_hover_sub_obj_placement_eval(obj);
+   else
+      _reval_content(obj);
+   _sizing_eval(obj);
+   if (evas_object_visible_get(wd->cov)) _hov_show_do(obj);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   edje_object_signal_emit(wd->cov, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   edje_object_signal_callback_add(wd->hov, emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+
+   edje_object_signal_callback_del_full(wd->hov, emission, source, func_cb,
+                                        data);
+}
+
+static void
+_elm_hover_left_space_calc(Widget_Data *wd, Evas_Coord *spc_l, Evas_Coord *spc_t, Evas_Coord *spc_r, Evas_Coord *spc_b)
+{
+   Evas_Coord x = 0, y = 0, w = 0, h = 0, x2 = 0, y2 = 0, w2 = 0, h2 = 0;
+
+   if (wd->parent)
+     evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
+   if (wd->target)
+     evas_object_geometry_get(wd->target, &x2, &y2, &w2, &h2);
+
+   *spc_l = x2 - x;
+   *spc_r = (x + w) - (x2 + w2);
+   if (*spc_l < 0)
+     *spc_l = 0;
+   if (*spc_r < 0)
+     *spc_r = 0;
+
+   *spc_t = y2 - y;
+   *spc_b = (y + h) - (y2 + h2);
+   if (*spc_t < 0)
+     *spc_t = 0;
+   if (*spc_b < 0)
+     *spc_b = 0;
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord x = 0, y = 0, w = 0, h = 0, x2 = 0, y2 = 0, w2 = 0, h2 = 0;
+   if (!wd) return;
+   if (wd->parent) evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
+   if (wd->hov) evas_object_geometry_get(wd->hov, &x2, &y2, &w2, &h2);
+   evas_object_move(wd->cov, x, y);
+   evas_object_resize(wd->cov, w, h);
+   evas_object_size_hint_min_set(wd->offset, x2 - x, y2 - y);
+   evas_object_size_hint_min_set(wd->size, w2, h2);
+   edje_object_part_swallow(wd->cov, "elm.swallow.offset", wd->offset);
+   edje_object_part_swallow(wd->cov, "elm.swallow.size", wd->size);
+}
+
+static void
+_reval_content(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   ELM_HOVER_PARTS_FOREACH
+     {
+        char buf[1024];
+        snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", wd->subs[i].swallow);
+        edje_object_part_swallow(wd->cov, buf, wd->subs[i].obj);
+     }
+}
+
+static const char *
+_elm_hover_smart_content_location_get(Widget_Data *wd,  Evas_Coord spc_l, Evas_Coord spc_t, Evas_Coord spc_r, Evas_Coord spc_b)
+{
+   Evas_Coord c_w = 0, c_h = 0, mid_w, mid_h;
+   int max;
+
+   evas_object_size_hint_min_get(wd->smt_sub, &c_w, &c_h);
+   mid_w = c_w / 2;
+   mid_h = c_h / 2;
+
+   if (spc_l > spc_r)
+     goto left;
+
+   max = MAX(spc_t, spc_r);
+   max = MAX(max, spc_b);
+
+   if (max == spc_t)
+     {
+        if (mid_w > spc_l)
+          return _HOV_TOP_RIGHT;
+
+        return _HOV_TOP;
+     }
+
+   if (max == spc_r)
+     {
+        if (mid_h > spc_t)
+          return _HOV_BOTTOM_RIGHT;
+        else if (mid_h > spc_b)
+          return _HOV_TOP_RIGHT;
+
+        return _HOV_RIGHT;
+     }
+
+   if (mid_h > spc_l)
+     return _HOV_BOTTOM_RIGHT;
+
+   return _HOV_BOTTOM;
+
+left:
+   max = MAX(spc_t, spc_l);
+   max = MAX(max, spc_b);
+
+   if (max == spc_t)
+     {
+        if (mid_w > spc_r)
+          return _HOV_TOP_LEFT;
+
+        return _HOV_TOP;
+     }
+
+   if (max == spc_l)
+     {
+        if (mid_h > spc_t)
+          return _HOV_BOTTOM_LEFT;
+        else if (mid_h > spc_b)
+          return _HOV_TOP_LEFT;
+
+        return _HOV_LEFT;
+     }
+
+   if (mid_h > spc_r)
+     return _HOV_BOTTOM_LEFT;
+
+   return _HOV_BOTTOM;
+}
+
+static void
+_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd;
+   Evas_Object *sub;
+
+   sub = event_info;
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (wd->smt_sub)
+     {
+        if (wd->smt_sub == sub)
+           wd->smt_sub = NULL;
+     }
+   else
+     {
+        ELM_HOVER_PARTS_FOREACH
+          {
+             if (wd->subs[i].obj == sub)
+               {
+                  wd->subs[i].obj = NULL;
+                  break;
+               }
+          }
+     }
+}
+
+static void
+_hov_show_do(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (wd->cov)
+     {
+       evas_object_show(wd->cov);
+       edje_object_signal_emit(wd->cov, "elm,action,show", "elm");
+     }
+
+   ELM_HOVER_PARTS_FOREACH
+     {
+       char buf[1024];
+
+       if (wd->subs[i].obj)
+         {
+            snprintf(buf, sizeof(buf), "elm,action,slot,%s,show",
+                     wd->subs[i].swallow);
+            edje_object_signal_emit(wd->cov, buf, "elm");
+         }
+     }
+}
+
+static void
+_hov_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_hov_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_hov_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _hov_show_do(data);
+}
+
+static void
+_hov_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->cov)
+     {
+       edje_object_signal_emit(wd->cov, "elm,action,hide", "elm");
+       evas_object_hide(wd->cov);
+     }
+
+   ELM_HOVER_PARTS_FOREACH
+     {
+       char buf[1024];
+
+       if (wd->subs[i].obj)
+         {
+            snprintf(buf, sizeof(buf), "elm,action,slot,%s,hide",
+                     wd->subs[i].swallow);
+            edje_object_signal_emit(wd->cov, buf, "elm");
+         }
+     }
+}
+
+static void
+_target_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->target = NULL;
+}
+
+static void
+_target_move(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);
+   _elm_hover_sub_obj_placement_eval(data);
+}
+
+static void
+_signal_dismiss(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_hide(data);
+   evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
+}
+
+static void
+_parent_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_parent_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+}
+
+static void
+_parent_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_hide(wd->cov);
+}
+
+static void
+_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   elm_hover_parent_set(data, NULL);
+   _sizing_eval(data);
+}
+
+/**
+ * Adds a hover object to @p parent
+ *
+ * @param parent The parent object
+ * @return The hover object or NULL if one could not be created
+ *
+ * @ingroup Hover
+ */
+EAPI Evas_Object *
+elm_hover_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+
+   ELM_HOVER_PARTS_FOREACH
+     wd->subs[i].swallow = _directions[i];
+
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "hover");
+   elm_widget_type_set(obj, "hover");
+   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_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+
+   wd->hov = evas_object_rectangle_add(e);
+   evas_object_pass_events_set(wd->hov, EINA_TRUE);
+   evas_object_color_set(wd->hov, 0, 0, 0, 0);
+   elm_widget_resize_object_set(obj, wd->hov);
+   evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_MOVE, _hov_move, obj);
+   evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_RESIZE, _hov_resize, obj);
+   evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_SHOW, _hov_show, obj);
+   evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_HIDE, _hov_hide, obj);
+
+   wd->cov = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->cov, "hover", "base", "default");
+   elm_widget_sub_object_add(obj, wd->cov);
+   edje_object_signal_callback_add(wd->cov, "elm,action,dismiss", "",
+                                   _signal_dismiss, obj);
+
+   wd->offset = evas_object_rectangle_add(e);
+   evas_object_pass_events_set(wd->offset, EINA_TRUE);
+   evas_object_color_set(wd->offset, 0, 0, 0, 0);
+   elm_widget_sub_object_add(obj, wd->offset);
+
+   wd->size = evas_object_rectangle_add(e);
+   evas_object_pass_events_set(wd->size, EINA_TRUE);
+   evas_object_color_set(wd->size, 0, 0, 0, 0);
+   elm_widget_sub_object_add(obj, wd->size);
+
+   edje_object_part_swallow(wd->cov, "elm.swallow.offset", wd->offset);
+   edje_object_part_swallow(wd->cov, "elm.swallow.size", wd->size);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   elm_hover_parent_set(obj, parent);
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Sets the target object for the hover.
+ *
+ * @param obj The hover object
+ * @param target The object to center the hover onto. The hover
+ * will take up the entire space that the target object fills.
+ *
+ * @ingroup Hover
+ */
+EAPI void
+elm_hover_target_set(Evas_Object *obj, Evas_Object *target)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (wd->target)
+     {
+        evas_object_event_callback_del_full(wd->target, EVAS_CALLBACK_DEL,
+                                            _target_del, obj);
+        evas_object_event_callback_del_full(wd->target, EVAS_CALLBACK_MOVE,
+                                            _target_move, obj);
+     }
+   wd->target = target;
+   if (wd->target)
+     {
+       evas_object_event_callback_add(wd->target, EVAS_CALLBACK_DEL,
+                                       _target_del, obj);
+       evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOVE,
+                                       _target_move, obj);
+       elm_widget_hover_object_set(target, obj);
+       _sizing_eval(obj);
+     }
+}
+
+
+/**
+ * Sets the parent object for the hover.
+ *
+ * @param obj The hover object
+ * @param parent The object to locate the hover over.
+ *
+ * @ingroup Hover
+ */
+EAPI void
+elm_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->parent)
+     {
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
+                                       _parent_move, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
+                                       _parent_resize, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_SHOW,
+                                       _parent_show, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
+                                       _parent_hide, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
+                                       _parent_del, obj);
+     }
+   wd->parent = parent;
+   if (wd->parent)
+     {
+       evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_MOVE,
+                                       _parent_move, obj);
+       evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE,
+                                       _parent_resize, obj);
+       evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_SHOW,
+                                       _parent_show, obj);
+       evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_HIDE,
+                                       _parent_hide, obj);
+       evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL,
+                                       _parent_del, obj);
+//     elm_widget_sub_object_add(parent, obj);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Gets the target object for the hover.
+ *
+ * @param obj The hover object
+ * @return The target object of the hover.
+ *
+ * @ingroup Hover
+ */
+EAPI Evas_Object *
+elm_hover_target_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->target;
+}
+
+/**
+ * Gets the parent object for the hover.
+ *
+ * @param obj The hover object
+ * @return The parent object to locate the hover over.
+ *
+ * @ingroup Hover
+ */
+EAPI Evas_Object *
+elm_hover_parent_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->parent;
+}
+
+static void
+_elm_hover_subs_del(Widget_Data *wd)
+{
+   ELM_HOVER_PARTS_FOREACH
+     {
+       if (wd->subs[i].obj)
+         {
+             evas_object_del(wd->subs[i].obj);
+             wd->subs[i].obj = NULL;
+         }
+     }
+}
+
+static void
+_elm_hover_sub_obj_placement_eval(Evas_Object *obj)
+{
+   Evas_Coord spc_l, spc_r, spc_t, spc_b;
+   const char *smart_dir;
+   Widget_Data *wd;
+   char buf[1024];
+
+   wd = elm_widget_data_get(obj);
+   if (!wd->smt_sub)
+     return;
+
+   _elm_hover_left_space_calc(wd, &spc_l, &spc_t, &spc_r, &spc_b);
+
+   edje_object_part_unswallow(wd->cov, wd->smt_sub);
+
+   smart_dir = _elm_hover_smart_content_location_get(wd, spc_l, spc_t, spc_r,
+                                                     spc_b);
+   evas_object_smart_callback_call(obj, SIG_SMART_LOCATION_CHANGED,
+                                   (void *)smart_dir);
+
+   snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", smart_dir);
+   edje_object_part_swallow(wd->cov, buf, wd->smt_sub);
+}
+
+static void
+_elm_hover_sub_obj_placement_eval_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _elm_hover_sub_obj_placement_eval(data);
+}
+
+/**
+ * Sets the content of the hover object and the direction in which
+ * it will pop out.
+ *
+ * Once the content object is set for a given direction, a previously
+ * set one (on the same direction) will be deleted. If you want to
+ * keep that old content object, use the elm_hover_content_unset()
+ * function.
+ *
+ * @param obj The hover object
+ * @param swallow The direction that the object will be displayed
+ * at. Accepted values are "left", "top-left", "top", "top-right",
+ * "right", "bottom-right", "bottom", "bottom-left", "middle" and
+ * "smart".
+ * @param content The content to place at @p swallow
+ *
+ * All directions may have contents at the same time, except for
+ * "smart". This is a special placement hint and its use case
+ * independs of the calculations coming from
+ * elm_hover_best_content_location_get(). Its use is for cases when
+ * one desires only one hover content, but with a dinamic special
+ * placement within the hover area. The content's geometry, whenever
+ * it changes, will be used to decide on a best location not
+ * extrapolating the hover's parent object view to show it in (still
+ * being the hover's target determinant of its medium part -- move and
+ * resize it to simulate finger sizes, for example). If one of the
+ * directions other than "smart" are used, a previously content set
+ * using it will be deleted, and vice-versa.
+ *
+ * @ingroup Hover
+ */
+EAPI void
+elm_hover_content_set(Evas_Object *obj, const char *swallow, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (!strcmp(swallow, "smart"))
+     {
+        if (wd->smt_sub != content)
+          {
+             _elm_hover_subs_del(wd);
+             wd->smt_sub = content;
+          }
+
+        if (content)
+          {
+             elm_widget_sub_object_add(obj, content);
+             evas_object_event_callback_add(wd->smt_sub,
+                                            EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _elm_hover_sub_obj_placement_eval_cb,
+                                            obj);
+
+             _elm_hover_sub_obj_placement_eval(obj);
+          }
+
+        goto end;
+     }
+
+   if (wd->smt_sub)
+     {
+        evas_object_del(wd->smt_sub);
+        wd->smt_sub = NULL;
+     }
+
+   ELM_HOVER_PARTS_FOREACH
+     {
+       if (!strcmp(swallow, wd->subs[i].swallow))
+         {
+            if (content == wd->subs[i].obj)
+               return;
+            evas_object_del(wd->subs[i].obj);
+             wd->subs[i].obj = NULL;
+
+             if (content)
+               {
+                  char buf[1024];
+
+                  snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", swallow);
+                  elm_widget_sub_object_add(obj, content);
+                  edje_object_part_swallow(wd->cov, buf, content);
+                  wd->subs[i].obj = content;
+               }
+            break;
+         }
+     }
+
+ end:
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the content of the hover object, in a given direction.
+ *
+ * Return the content object which was set for this widget in the
+ * given direction.
+ *
+ * @param obj The hover object
+ * @param swallow The direction that the object was display at.
+ * @return The content that was being used
+ *
+ * @note See elm_hover_content_set() for more information.
+ *
+ * @ingroup Hover
+ */
+EAPI Evas_Object *
+elm_hover_content_get(const Evas_Object *obj, const char *swallow)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return NULL;
+
+   if (!strcmp(swallow, "smart"))
+     return wd->smt_sub;
+
+   ELM_HOVER_PARTS_FOREACH
+     if (!strcmp(swallow, wd->subs[i].swallow))
+       return wd->subs[i].obj;
+
+   return NULL;
+}
+
+static void
+_elm_hover_sub_obj_unparent(Evas_Object *obj)
+{
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+
+   elm_widget_sub_object_del(obj, wd->smt_sub);
+   evas_object_event_callback_del_full(wd->smt_sub,
+                                       EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _elm_hover_sub_obj_placement_eval_cb,
+                                       obj);
+   edje_object_part_unswallow(wd->cov, wd->smt_sub);
+   wd->smt_sub = NULL;
+}
+
+/**
+ * Unset the content of the hover object, in a given direction.
+ *
+ * Unparent and return the content object set at that direction.
+ *
+ * @param obj The hover object
+ * @param swallow The direction that the object was display at.
+ * @return The content that was being used.
+ *
+ * @note See elm_hover_content_set() for more information.
+ *
+ * @ingroup Hover
+ */
+EAPI Evas_Object *
+elm_hover_content_unset(Evas_Object *obj, const char *swallow)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return NULL;
+
+   if (!strcmp(swallow, "smart"))
+     {
+        Evas_Object *content;
+
+        if (!wd->smt_sub)
+          return NULL;
+
+        content = wd->smt_sub;
+        _elm_hover_sub_obj_unparent(obj);
+        return content;
+     }
+
+   ELM_HOVER_PARTS_FOREACH
+     {
+       if (!strcmp(swallow, wd->subs[i].swallow))
+         {
+            Evas_Object *content;
+
+            if (!wd->subs[i].obj)
+               return NULL;
+
+            content = wd->subs[i].obj;
+            elm_widget_sub_object_del(obj, wd->subs[i].obj);
+            edje_object_part_unswallow(wd->cov, wd->subs[i].obj);
+            wd->subs[i].obj = NULL;
+
+            return content;
+         }
+     }
+
+   return NULL;
+}
+
+/**
+ * Returns the best swallow location for content in the hover.
+ *
+ * @param obj The hover object
+ * @param pref_axis The preferred orientation axis for the hover object to use
+ * @return The edje location to place content into the hover or @c
+ *         NULL, on errors.
+ *
+ * @p pref_axis may be one of
+ * <ul>
+ * - @c ELM_HOVER_AXIS_NONE -- no prefered orientation
+ * - @c ELM_HOVER_AXIS_HORIZONTAL -- horizontal
+ * - @c ELM_HOVER_AXIS_VERTICAL -- vertical
+ * - @c ELM_HOVER_AXIS_BOTH -- both
+ * </ul>
+ *
+ * See also elm_hover_content_set().
+ *
+ * @ingroup Hover
+ */
+EAPI const char *
+elm_hover_best_content_location_get(const Evas_Object *obj, Elm_Hover_Axis pref_axis)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   Evas_Coord spc_l, spc_r, spc_t, spc_b;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return NULL;
+
+   _elm_hover_left_space_calc(wd, &spc_l, &spc_t, &spc_r, &spc_b);
+
+   if (pref_axis == ELM_HOVER_AXIS_HORIZONTAL)
+     {
+       if (spc_l < spc_r) return _HOV_RIGHT;
+       else return _HOV_LEFT;
+     }
+   else if (pref_axis == ELM_HOVER_AXIS_VERTICAL)
+     {
+       if (spc_t < spc_b) return _HOV_BOTTOM;
+       else return _HOV_TOP;
+     }
+
+   if (spc_l < spc_r)
+     {
+        if (spc_t > spc_r) return _HOV_TOP;
+        else if (spc_b > spc_r) return _HOV_BOTTOM;
+        return _HOV_RIGHT;
+     }
+   if (spc_t > spc_r) return _HOV_TOP;
+   else if (spc_b > spc_r) return _HOV_BOTTOM;
+   return _HOV_LEFT;
+}
diff --git a/src/lib/elm_icon.c b/src/lib/elm_icon.c
new file mode 100644 (file)
index 0000000..c0fad61
--- /dev/null
@@ -0,0 +1,651 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#ifdef ELM_EFREET
+#define NON_EXISTING (void *)-1
+static const char *icon_theme = NULL;
+#endif
+
+/**
+ * @defgroup Icon Icon
+ *
+ * A standard icon that may be provided by the theme (delete, edit,
+ * arrows etc.) or a custom file (PNG, JPG, EDJE etc.) used for an
+ * icon. The Icon may scale or not and of course... support alpha
+ * channels.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * clicked - This is called when a user has clicked the icon
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *img;
+   const char *stdicon;
+   Elm_Icon_Lookup_Order lookup_order;
+#ifdef ELM_EFREET
+   struct {
+      int requested_size;
+      Eina_Bool use : 1;
+   } freedesktop;
+#endif
+   Eina_Bool scale_up : 1;
+   Eina_Bool scale_down : 1;
+   Eina_Bool smooth : 1;
+   Eina_Bool fill_outside : 1;
+   Eina_Bool no_scale : 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 _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static Eina_Bool _icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name);
+static Eina_Bool _icon_freedesktop_set(Widget_Data *wd, Evas_Object *obj, const char *name, int size);
+
+//FIXME: move this code to ecore
+#ifdef _WIN32
+static Eina_Bool
+_path_is_absolute(const char *path)
+{
+   //TODO: Check if this works with all absolute paths in windows
+   return ((isalpha (*path)) && (*(path + 1) == ':') && ((*(path + 2) == '\\') || (*(path + 2) == '/')));
+}
+#else
+static Eina_Bool
+_path_is_absolute(const char *path)
+{
+   return  (*path == '/');
+}
+#endif
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   if (wd->stdicon) eina_stringshare_del(wd->stdicon);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->stdicon)
+     _elm_theme_object_icon_set(obj, wd->img, wd->stdicon, elm_widget_style_get(obj));
+   _sizing_eval(obj);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   Evas_Object *icon_edje;
+   icon_edje = _els_smart_icon_edje_get(wd->img);
+   if (!icon_edje) return;
+   edje_object_signal_emit(icon_edje, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   Evas_Object *icon_edje;
+   icon_edje = _els_smart_icon_edje_get(wd->img);
+   if (!icon_edje) return;
+   edje_object_signal_callback_add(icon_edje, emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   Evas_Object *icon_edje;
+   icon_edje = _els_smart_icon_edje_get(wd->img);
+   if (!icon_edje) return;
+   edje_object_signal_callback_del_full(icon_edje, emission, source, func_cb,
+                                        data);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+   int w, h;
+
+   _els_smart_icon_size_get(wd->img, &w, &h);
+#ifdef ELM_EFREET
+   if ((wd->freedesktop.use) && (!((w - wd->freedesktop.requested_size) % 16)))
+     {
+        /* This icon has been set to a freedesktop icon, and the requested
+           appears to have a different size than the requested size, so try to
+           request another, higher resolution, icon.
+           FIXME: Find a better heuristic to determine if there should be
+           an icon with a different resolution. */
+        _icon_freedesktop_set(wd, obj, wd->stdicon, w);
+     }
+#endif
+   _els_smart_icon_scale_up_set(wd->img, wd->scale_up);
+   _els_smart_icon_scale_down_set(wd->img, wd->scale_down);
+   _els_smart_icon_smooth_scale_set(wd->img, wd->smooth);
+   _els_smart_icon_fill_inside_set(wd->img, !(wd->fill_outside));
+   if (wd->no_scale) _els_smart_icon_scale_set(wd->img, 1.0);
+   else
+     {
+       _els_smart_icon_scale_set(wd->img, elm_widget_scale_get(obj) *
+                                 _elm_config->scale);
+       _els_smart_icon_size_get(wd->img, &w, &h);
+     }
+   if (!wd->scale_down)
+     {
+       minw = w;
+       minh = h;
+     }
+   if (!wd->scale_up)
+     {
+       maxw = w;
+       maxh = h;
+     }
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Up *ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+   evas_object_smart_callback_call(data, "clicked", event_info);
+}
+
+/**
+ * Add a new icon to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Icon
+ */
+EAPI Evas_Object *
+elm_icon_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "icon");
+   elm_widget_type_set(obj, "icon");
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+   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_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+
+   wd->lookup_order = ELM_ICON_LOOKUP_THEME_FDO;
+   wd->img = _els_smart_icon_add(e);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
+                                 _mouse_up, obj);
+   evas_object_repeat_events_set(wd->img, EINA_TRUE);
+   elm_widget_resize_object_set(obj, wd->img);
+
+   wd->smooth = EINA_TRUE;
+   wd->scale_up = EINA_TRUE;
+   wd->scale_down = EINA_TRUE;
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the file that will be used as icon
+ *
+ * @param obj The icon object
+ * @param file The path to file that will be used as icon
+ * @param group The group that the icon belongs in edje file
+ *
+ * @return (1 = success, 0 = error)
+ *
+ * @ingroup Icon
+ */
+EAPI Eina_Bool
+elm_icon_file_set(Evas_Object *obj, const char *file, const char *group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Bool ret;
+   const char *p;
+
+   if (!wd) return EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
+   if (wd->stdicon) eina_stringshare_del(wd->stdicon);
+   wd->stdicon = NULL;
+   if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
+     ret = _els_smart_icon_file_edje_set(wd->img, file, group);
+   else
+     ret = _els_smart_icon_file_key_set(wd->img, file, group);
+   _sizing_eval(obj);
+   return ret;
+}
+
+/**
+ * Get the file that will be used as icon
+ *
+ * @param obj The icon object
+ * @param file The path to file that will be used as icon
+ * @param group The group that the icon belongs in edje file
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_file_get(const Evas_Object *obj, const char **file, const char **group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _els_smart_icon_file_get(wd->img, file, group);
+}
+
+static Eina_Bool
+_icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name)
+{
+   if (_elm_theme_object_icon_set(obj, wd->img, name, "default"))
+     {
+#ifdef ELM_EFREET
+        /* TODO: elm_unneed_efreet() */
+        wd->freedesktop.use = EINA_FALSE;
+#endif
+        return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_icon_file_set(Widget_Data *wd, Evas_Object *obj, const char *path)
+{
+   if (elm_icon_file_set(obj, path, NULL))
+     {
+#ifdef ELM_EFREET
+        /* TODO: elm_unneed_efreet() */
+        wd->freedesktop.use = EINA_FALSE;
+#endif
+        return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_icon_freedesktop_set(Widget_Data *wd, Evas_Object *obj, const char *name, int size)
+{
+#ifdef ELM_EFREET
+   const char *path;
+
+   elm_need_efreet();
+   if (icon_theme == NON_EXISTING) return EINA_FALSE;
+   if (!icon_theme)
+     {
+        Efreet_Icon_Theme *theme;
+        /* TODO: Listen for EFREET_EVENT_ICON_CACHE_UPDATE */
+        theme = efreet_icon_theme_find(getenv("E_ICON_THEME"));
+        if (!theme)
+          {
+             const char **itr;
+             static const char *themes[] = {
+                  "gnome", "Human", "oxygen", "hicolor", NULL
+             };
+             for (itr = themes; *itr; itr++)
+               {
+                  theme = efreet_icon_theme_find(*itr);
+                  if (theme) break;
+               }
+          }
+
+        if (!theme)
+          {
+             icon_theme = NON_EXISTING;
+             return EINA_FALSE;
+          }
+        else
+          icon_theme = eina_stringshare_add(theme->name.internal);
+     }
+   path = efreet_icon_path_find(icon_theme, name, size);
+   wd->freedesktop.use = !!path;
+   if (wd->freedesktop.use)
+     {
+        wd->freedesktop.requested_size = size;
+        elm_icon_file_set(obj, path, NULL);
+        return EINA_TRUE;
+     }
+#endif
+   return EINA_FALSE;
+}
+
+static inline int
+_icon_size_min_get(Evas_Object *icon)
+{
+   int size;
+   _els_smart_icon_size_get(icon, &size, NULL);
+   return (size < 32) ? 32 : size;
+}
+
+/**
+ * Set the theme, as standard, for a icon.
+ * If theme was not found and it is the absolute path of an image file, this
+ * image will be used.
+ *
+ * @param obj The icon object
+ * @param name The theme name
+ *
+ * @return (1 = success, 0 = error)
+ *
+ * @ingroup Icon
+ */
+EAPI Eina_Bool
+elm_icon_standard_set(Evas_Object *obj, const char *name)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char *tmp;
+   Eina_Bool ret;
+
+   if ((!wd) || (!name)) return EINA_FALSE;
+
+   /* try locating the icon using the specified lookup order */
+   switch (wd->lookup_order)
+   {
+   case ELM_ICON_LOOKUP_FDO:
+      ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
+      break;
+   case ELM_ICON_LOOKUP_THEME:
+      ret = _icon_standard_set(wd, obj, name);
+      break;
+   case ELM_ICON_LOOKUP_THEME_FDO:
+      ret = _icon_standard_set(wd, obj, name) ||
+            _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
+      break;
+   case ELM_ICON_LOOKUP_FDO_THEME:
+   default:
+      ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img)) ||
+            _icon_standard_set(wd, obj, name);
+      break;
+   }
+
+   if (ret)
+     {
+        eina_stringshare_replace(&wd->stdicon, name);
+        _sizing_eval(obj);
+        return EINA_TRUE;
+     }
+
+   if (_path_is_absolute(name))
+      return _icon_file_set(wd, obj, name);
+
+   /* if that fails, see if icon name is in the format size/name. if so,
+      try locating a fallback without the size specification */
+   if (!(tmp = strchr(name, '/'))) return EINA_FALSE;
+   ++tmp;
+   if (*tmp) return elm_icon_standard_set(obj, tmp);
+
+   /* give up */
+   return EINA_FALSE;
+}
+
+/**
+ * Get the theme, as standard, for a icon
+ *
+ * @param obj The icon object
+ * @return The theme name
+ *
+ * @ingroup Icon
+ */
+EAPI const char *
+elm_icon_standard_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->stdicon;
+}
+
+/**
+ * Sets icon lookup order, used by elm_icon_standard_set().
+ *
+ * @param obj The icon object
+ * @param order The icon lookup order
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (wd) wd->lookup_order = order;
+}
+
+/**
+ * Gets the icon lookup order.
+ *
+ * @param obj The icon object
+ * @return The icon lookup order
+ *
+ * @ingroup Icon
+ */
+EAPI Elm_Icon_Lookup_Order
+elm_icon_order_lookup_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
+   return wd->lookup_order;
+}
+
+/**
+ * Set the smooth effect for a icon
+ *
+ * @param obj The icon object
+ * @param smooth A bool to set (or no) smooth effect
+ * (1 = smooth, 0 = not smooth)
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_smooth_set(Evas_Object *obj, Eina_Bool smooth)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->smooth = smooth;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the smooth effect for a icon
+ *
+ * @param obj The icon object
+ * @return If setted smooth effect
+ *
+ * @ingroup Icon
+ */
+EAPI Eina_Bool
+elm_icon_smooth_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->smooth;
+}
+
+/**
+ * Set if the object is scalable
+ *
+ * @param obj The icon object
+ * @param no_scale A bool to set scale (or no)
+ * (1 = no_scale, 0 = scale)
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_no_scale_set(Evas_Object *obj, Eina_Bool no_scale)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->no_scale = no_scale;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get if the object isn't scalable
+ *
+ * @param obj The icon object
+ * @return If isn't scalable
+ *
+ * @ingroup Icon
+ */
+EAPI Eina_Bool
+elm_icon_no_scale_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_scale;
+}
+
+/**
+ * Set if the object is (up/down) scalable
+ *
+ * @param obj The icon object
+ * @param scale_up A bool to set if the object is scalable up
+ * @param scale_down A bool to set if the object is scalable down
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_scale_set(Evas_Object *obj, Eina_Bool scale_up, Eina_Bool scale_down)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->scale_up = scale_up;
+   wd->scale_down = scale_down;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get if the object is (up/down) scalable
+ *
+ * @param obj The icon object
+ * @param scale_up A bool to set if the object is scalable up
+ * @param scale_down A bool to set if the object is scalable down
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_scale_get(const Evas_Object *obj, Eina_Bool *scale_up, Eina_Bool *scale_down)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (scale_up) *scale_up = wd->scale_up;
+   if (scale_down) *scale_down = wd->scale_down;
+}
+
+/**
+ * Set if the object is filled outside
+ *
+ * @param obj The icon object
+ * @param fill_outside A bool to set if the object is filled outside
+ * (1 = filled, 0 = no filled)
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->fill_outside = fill_outside;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get if the object is filled outside
+ *
+ * @param obj The icon object
+ * @return If the object is filled outside
+ *
+ * @ingroup Icon
+ */
+EAPI Eina_Bool
+elm_icon_fill_outside_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->fill_outside;
+}
+
+/**
+ * Set the prescale size for the icon
+ *
+ * @param obj The icon object
+ * @param size The prescale size
+ *
+ * @ingroup Icon
+ */
+EAPI void
+elm_icon_prescale_set(Evas_Object *obj, int size)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   _els_smart_icon_scale_size_set(wd->img, size);
+}
+
+/**
+ * Get the prescale size for the icon
+ *
+ * @param obj The icon object
+ * @return The prescale size
+ *
+ * @ingroup Icon
+ */
+EAPI int
+elm_icon_prescale_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return 0;
+   return _els_smart_icon_scale_size_get(wd->img);
+}
diff --git a/src/lib/elm_image.c b/src/lib/elm_image.c
new file mode 100644 (file)
index 0000000..a71fe11
--- /dev/null
@@ -0,0 +1,487 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Image Image
+ *
+ * A standard image that may be provided by the theme (delete, edit,
+ * arrows etc.) or a custom file (PNG, JPG, EDJE etc.) used for an
+ * icon. The Icon may scale or not and of course... support alpha
+ * channels.
+ * 
+ * Signals that you can add callbacks for are:
+ *
+ *  - clicked: This is called when a user has clicked the image
+ *  - drop: Something has been dropped on the image
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *img;
+   Eina_Bool scale_up : 1;
+   Eina_Bool scale_down : 1;
+   Eina_Bool smooth : 1;
+   Eina_Bool fill_outside : 1;
+   Eina_Bool no_scale : 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 _mouse_up(void *data, Evas *e, 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
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   evas_object_del(wd->img);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   _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;
+   int w, h;
+
+   if (!wd) return;
+   _els_smart_icon_size_get(wd->img, &w, &h);
+   _els_smart_icon_scale_up_set(wd->img, wd->scale_up);
+   _els_smart_icon_scale_down_set(wd->img, wd->scale_down);
+   _els_smart_icon_smooth_scale_set(wd->img, wd->smooth);
+   _els_smart_icon_fill_inside_set(wd->img, !(wd->fill_outside));
+   if (wd->no_scale) _els_smart_icon_scale_set(wd->img, 1.0);
+   else
+     {
+       _els_smart_icon_scale_set(wd->img, elm_widget_scale_get(obj) * _elm_config->scale);
+       _els_smart_icon_size_get(wd->img, &w, &h);
+     }
+   if (!wd->scale_down)
+     {
+       minw = w;
+       minh = h;
+     }
+   if (!wd->scale_up)
+     {
+       maxw = w;
+       maxh = h;
+     }
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "clicked", NULL);
+}
+
+/**
+ * Add a new image to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Image
+ */
+EAPI Evas_Object *
+elm_image_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "image");
+   elm_widget_type_set(obj, "image");
+   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);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->img = _els_smart_icon_add(e);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
+                                 _mouse_up, obj);
+   evas_object_repeat_events_set(wd->img, EINA_TRUE);
+   elm_widget_resize_object_set(obj, wd->img);
+
+   wd->smooth = EINA_TRUE;
+   wd->scale_up = EINA_TRUE;
+   wd->scale_down = EINA_TRUE;
+
+   _els_smart_icon_scale_size_set(wd->img, 0);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the file that will be used as image
+ *
+ * @param obj The image object
+ * @param file The path to file that will be used as image
+ * @param group The group that the image belongs in edje file
+ *
+ * @return (1 = success, 0 = error)
+ *
+ * @ingroup Image
+ */
+EAPI Eina_Bool
+elm_image_file_set(Evas_Object *obj, const char *file, const char *group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Bool ret;
+   const char *p;
+
+   if (!wd) return EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
+   if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
+     ret = _els_smart_icon_file_edje_set(wd->img, file, group);
+   else
+     ret = _els_smart_icon_file_key_set(wd->img, file, group);
+   _sizing_eval(obj);
+   return ret;
+}
+
+/**
+ * Get the file that will be used as image
+ *
+ * @param obj The image object
+ * @param file The path to file
+ * @param group The group that the image belongs in edje file
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_file_get(const Evas_Object *obj, const char **file, const char **group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _els_smart_icon_file_get(wd->img, file, group);
+}
+
+/**
+ * Set the smooth effect for a image
+ *
+ * @param obj The image object
+ * @param smooth A bool to set (or no) smooth effect
+ * (1 = smooth, 0 = not smooth)
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_smooth_set(Evas_Object *obj, Eina_Bool smooth)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->smooth = smooth;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the smooth effect for a image
+ *
+ * @param obj The image object
+ * @return If setted smooth effect
+ *
+ * @ingroup Image
+ */
+EAPI Eina_Bool
+elm_image_smooth_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->smooth;
+}
+
+/**
+ * Gets the current size of the image.
+ *
+ * Either width or height (or both) may be NULL.
+ *
+ * On error, neither w or h will be written too.
+ *
+ * @param obj The image object.
+ * @param w Pointer to store width, or NULL.
+ * @param h Pointer to store height, or NULL.
+ */
+EAPI void
+elm_image_object_size_get(const Evas_Object *obj, int *w, int *h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   _els_smart_icon_size_get(wd->img, w, h);
+}
+
+/**
+ * Set if the object are scalable
+ *
+ * @param obj The image object.
+ * @param no_scale A bool to set scale (or no).
+ * (1 = no_scale, 0 = scale)
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_no_scale_set(Evas_Object *obj, Eina_Bool no_scale)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->no_scale = no_scale;
+   _sizing_eval(obj);
+
+}
+
+/**
+ * Get if the object isn't scalable
+ *
+ * @param obj The image object
+ * @return If isn't scalable
+ *
+ * @ingroup Image
+ */
+EAPI Eina_Bool
+elm_image_no_scale_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_scale;
+}
+
+/**
+ * Set if the object is (up/down) scalable
+ *
+ * @param obj The image object
+ * @param scale_up A bool to set if the object is scalable up
+ * @param scale_down A bool to set if the object is scalable down
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_scale_set(Evas_Object *obj, Eina_Bool scale_up, Eina_Bool scale_down)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->scale_up = scale_up;
+   wd->scale_down = scale_down;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get if the object is (up/down) scalable
+ *
+ * @param obj The image object
+ * @param scale_up A bool to set if the object is scalable up
+ * @param scale_down A bool to set if the object is scalable down
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_scale_get(const Evas_Object *obj, Eina_Bool *scale_up, Eina_Bool *scale_down)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (scale_up) *scale_up = wd->scale_up;
+   if (scale_down) *scale_down = wd->scale_down;
+}
+
+/**
+ * Set if the object is filled outside
+ *
+ * @param obj The image object
+ * @param fill_outside A bool to set if the object is filled outside
+ * (1 = filled, 0 = no filled)
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->fill_outside = fill_outside;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get if the object is filled outside
+ *
+ * @param obj The image object
+ * @return If the object is filled outside
+ *
+ * @ingroup Image
+ */
+EAPI Eina_Bool
+elm_image_fill_outside_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->fill_outside;
+}
+
+/**
+ * Set the prescale size for the image
+ *
+ * @param obj The image object
+ * @param size The prescale size
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_prescale_set(Evas_Object *obj, int size)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   _els_smart_icon_scale_size_set(wd->img, size);
+}
+
+/**
+ * Get the prescale size for the image
+ *
+ * @param obj The image object
+ * @return The prescale size
+ *
+ * @ingroup Image
+ */
+EAPI int
+elm_image_prescale_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return 0;
+   return _els_smart_icon_scale_size_get(wd->img);
+}
+
+/**
+ * Set the image orient
+ *
+ * @param obj The image object
+ * @param orient The image orient
+ * (ELM_IMAGE_ORIENT_NONE, ELM_IMAGE_ROTATE_90_CW,
+ *  ELM_IMAGE_ROTATE_180_CW, ELM_IMAGE_ROTATE_90_CCW,
+ *  ELM_IMAGE_FLIP_HORIZONTAL,ELM_IMAGE_FLIP_VERTICAL,
+ *  ELM_IMAGE_FLIP_TRANSPOSE, ELM_IMAGE_FLIP_TRANSVERSE)
+ *
+ * @ingroup Image
+ */
+EAPI void
+elm_image_orient_set(Evas_Object *obj, Elm_Image_Orient orient)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   _els_smart_icon_orient_set(wd->img, orient);
+}
+
+/**
+ * Get the image orient
+ *
+ * @param obj The image object
+ * @return The image orient
+ * (ELM_IMAGE_ORIENT_NONE, ELM_IMAGE_ROTATE_90_CW,
+ *  ELM_IMAGE_ROTATE_180_CW, ELM_IMAGE_ROTATE_90_CCW,
+ *  ELM_IMAGE_FLIP_HORIZONTAL,ELM_IMAGE_FLIP_VERTICAL,
+ *  ELM_IMAGE_FLIP_TRANSPOSE, ELM_IMAGE_FLIP_TRANSVERSE)
+ *
+ * @ingroup Image
+ */
+EAPI Elm_Image_Orient
+elm_image_orient_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_IMAGE_ORIENT_NONE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_IMAGE_ORIENT_NONE;
+   return _els_smart_icon_orient_get(wd->img);
+}
+
+/**
+ * Make the image 'editable'.
+ *
+ * This means the image is a valid drag target for drag and drop, and can be
+ * cut or pasted too.
+ *
+ * @param obj Image object.
+ * @param set Turn on or off editability.
+ */
+EAPI void
+elm_image_editable_set(Evas_Object *obj, Eina_Bool set)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   _els_smart_icon_edit_set(wd->img, set, obj);
+}
+
+/**
+ * Make the image 'editable'.
+ *
+ * This means the image is a valid drag target for drag and drop, and can be
+ * cut or pasted too.
+ *
+ * @param obj Image object.
+ * @return Editability.
+ */
+EAPI Eina_Bool
+elm_image_editable_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 _els_smart_icon_edit_get(wd->img);
+}
+
+
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/src/lib/elm_index.c b/src/lib/elm_index.c
new file mode 100644 (file)
index 0000000..c63a2a4
--- /dev/null
@@ -0,0 +1,959 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Index Index
+ *
+ * An index object is a type of list that categorizes items in it
+ * by letter.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *base;
+   Evas_Object *event[2];
+   Evas_Object *bx[2]; // 2 - for now all that's supported
+   Eina_List *items; // 1 list. yes N levels, but only 2 for now and # of items will be small
+   int level;
+   Evas_Coord dx, dy;
+   Ecore_Timer *delay;
+   Eina_Bool level_active[2];
+   Eina_Bool horizontal : 1;
+   Eina_Bool active : 1;
+   Eina_Bool down : 1;
+};
+
+struct _Elm_Index_Item
+{
+   Elm_Widget_Item base;
+   const char *letter;
+   int level;
+   Eina_Bool selected : 1;
+};
+
+static const char *widtype = NULL;
+static void _theme_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level);
+static void _index_box_clear(Evas_Object *obj, Evas_Object *box, int level);
+static void _item_free(Elm_Index_Item *it);
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+   _index_box_clear(obj, wd->bx[0], 0);
+   while (wd->items) _item_free(wd->items->data);
+   if (wd->delay) ecore_timer_del(wd->delay);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   free(wd);
+}
+
+static void
+_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
+{
+   Widget_Data *wd = data;
+   if (!wd) return;
+   _els_box_layout(o, priv, wd->horizontal, 1);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(wd->base, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_add(wd->base, emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(wd->base, emission, source, func_cb,
+                                        data);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Evas_Coord minw = 0, minh = 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _index_box_clear(obj, wd->bx[0], 0);
+   _index_box_clear(obj, wd->bx[1], 1);
+   if (wd->horizontal)
+     _elm_theme_object_set(obj, wd->base, "index", "base/horizontal", elm_widget_style_get(obj));
+   else
+     _elm_theme_object_set(obj, wd->base, "index", "base/vertical", elm_widget_style_get(obj));
+   edje_object_part_swallow(wd->base, "elm.swallow.event.0", wd->event[0]);
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_size_hint_min_set(wd->event[0], minw, minh);
+   edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
+   if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
+     {
+        if (!wd->bx[1])
+          {
+            wd->bx[1] = evas_object_box_add(evas_object_evas_get(wd->base));
+            evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
+             elm_widget_sub_object_add(obj, wd->bx[1]);
+          }
+        edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
+        evas_object_show(wd->bx[1]);
+     }
+   else if (wd->bx[1])
+     {
+        evas_object_del(wd->bx[1]);
+        wd->bx[1] = NULL;
+     }
+   if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
+     {
+        if (!wd->event[1])
+          {
+             wd->event[1] = evas_object_rectangle_add(evas_object_evas_get(wd->base));
+             evas_object_color_set(wd->event[1], 0, 0, 0, 0);
+             elm_widget_sub_object_add(obj, wd->event[1]);
+          }
+        edje_object_part_swallow(wd->base, "elm.swallow.event.1", wd->event[1]);
+        evas_object_size_hint_min_set(wd->event[1], minw, minh);
+     }
+   else if (wd->event[1])
+     {
+        evas_object_del(wd->event[1]);
+        wd->event[1] = NULL;
+     }
+   edje_object_message_signal_process(wd->base);
+   edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
+   _sizing_eval(obj);
+   _index_box_auto_fill(obj, wd->bx[0], 0);
+   if (wd->active)
+     if (wd->level == 1)
+       _index_box_auto_fill(obj, wd->bx[1], 1);
+}
+
+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->base, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static Elm_Index_Item *
+_item_new(Evas_Object *obj, const char *letter, const void *item)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it;
+   if (!wd) return NULL;
+   it = elm_widget_item_new(obj, Elm_Index_Item);
+   if (!it) return NULL;
+   it->letter = eina_stringshare_add(letter);
+   it->base.data = item;
+   it->level = wd->level;
+   return it;
+}
+
+static Elm_Index_Item *
+_item_find(Evas_Object *obj, const void *item)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Index_Item *it;
+   if (!wd) return NULL;
+   EINA_LIST_FOREACH(wd->items, l, it)
+     if (it->base.data == item) return it;
+   return NULL;
+}
+
+static void
+_item_free(Elm_Index_Item *it)
+{
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   if (!wd) return;
+   wd->items = eina_list_remove(wd->items, it);
+   elm_widget_item_pre_notify_del(it);
+   eina_stringshare_del(it->letter);
+   elm_widget_item_del(it);
+}
+
+// FIXME: always have index filled
+static void
+_index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Index_Item *it;
+   Evas_Coord mw, mh, w, h;
+   int i = 0;
+   if (!wd) return;
+   if (wd->level_active[level]) return;
+   evas_object_geometry_get(box, NULL, NULL, &w, &h);
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+        Evas_Object *o;
+        const char *stacking;
+
+        if (it->level != level) continue;
+        o = edje_object_add(evas_object_evas_get(obj));
+        it->base.view = o;
+        if (i & 0x1)
+          _elm_theme_object_set(obj, o, "index", "item_odd/vertical", elm_widget_style_get(obj));
+        else
+          _elm_theme_object_set(obj, o, "index", "item/vertical", elm_widget_style_get(obj));
+        edje_object_part_text_set(o, "elm.text", it->letter);
+        edje_object_size_min_restricted_calc(o, &mw, &mh, 0, 0);
+        evas_object_size_hint_min_set(o, mw, mh);
+        evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        elm_widget_sub_object_add(obj, o);
+        evas_object_box_append(box, o);
+        stacking = edje_object_data_get(o, "stacking");
+        if (stacking)
+          {
+             if (!strcmp(stacking, "below")) evas_object_lower(o);
+             else if (!strcmp(stacking, "above")) evas_object_raise(o);
+          }
+        evas_object_show(o);
+        i++;
+        evas_object_smart_calculate(box); // force a calc so we know the size
+        evas_object_size_hint_min_get(box, &mw, &mh);
+        if (mh > h)
+          {
+             _index_box_clear(obj, box, level);
+             if (i > 0)
+               {
+                  // FIXME: only i objects fit! try again. overflows right now
+               }
+          }
+     }
+   evas_object_smart_calculate(box);
+   wd->level_active[level] = 1;
+}
+
+static void
+_index_box_clear(Evas_Object *obj, Evas_Object *box __UNUSED__, int level)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Index_Item *it;
+   if (!wd) return;
+   if (!wd->level_active[level]) return;
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+        if (!it->base.view) continue;
+        if (it->level != level) continue;
+        evas_object_del(it->base.view);
+        it->base.view = NULL;
+     }
+   wd->level_active[level] = 0;
+}
+
+static Eina_Bool
+_delay_change(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   void *d;
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->delay = NULL;
+   d = (void *)elm_index_item_selected_get(data, wd->level);
+   if (d) evas_object_smart_callback_call(data, "delay,changed", d);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_sel_eval(Evas_Object *obj, Evas_Coord evx, Evas_Coord evy)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it, *it_closest, *it_last;
+   Eina_List *l;
+   Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
+   double cdv = 0.5;
+   Evas_Coord dist;
+   char *label = NULL, *last = NULL;
+   int i;
+   if (!wd) return;
+   for (i = 0; i <= wd->level; i++)
+     {
+        it_last = NULL;
+        it_closest  = NULL;
+        dist = 0x7fffffff;
+        evas_object_geometry_get(wd->bx[i], &bx, &by, &bw, &bh);
+        EINA_LIST_FOREACH(wd->items, l, it)
+          {
+             if (!((it->level == i) && (it->base.view))) continue;
+             if ((it->base.view) && (it->level != wd->level))
+               {
+                  if (it->selected)
+                    {
+                       it_closest = it;
+                       break;
+                    }
+                  continue;
+               }
+             if (it->selected)
+               {
+                  it_last = it;
+                  it->selected = 0;
+               }
+             evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
+             xx = x + (w / 2);
+             yy = y + (h / 2);
+             x = evx - xx;
+             y = evy - yy;
+             x = (x * x) + (y * y);
+             if ((x < dist) || (!it_closest))
+               {
+                  if (wd->horizontal)
+                    cdv = (double)(xx - bx) / (double)bw; 
+                  else
+                    cdv = (double)(yy - by) / (double)bh;
+                  it_closest = it;
+                  dist = x;
+               }
+          }
+        if ((!i) && (!wd->level))
+          edje_object_part_drag_value_set(wd->base, "elm.dragable.index.1", 
+                                          cdv, cdv);
+        if (it_closest) it_closest->selected = 1;
+        if (it_closest != it_last)
+          {
+             if (it_last)
+               {
+                  const char *stacking, *selectraise;
+
+                  it = it_last;
+                  edje_object_signal_emit(it->base.view, "elm,state,inactive", "elm");
+                  stacking = edje_object_data_get(it->base.view, "stacking");
+                  selectraise = edje_object_data_get(it->base.view, "selectraise");
+                  if ((selectraise) && (!strcmp(selectraise, "on")))
+                    {
+                       if ((stacking) && (!strcmp(stacking, "below")))
+                         evas_object_lower(it->base.view);
+                    }
+               }
+             if (it_closest)
+               {
+                  const char *selectraise;
+
+                  it = it_closest;
+                  edje_object_signal_emit(it->base.view, "elm,state,active", "elm");
+                  selectraise = edje_object_data_get(it->base.view, "selectraise");
+                  if ((selectraise) && (!strcmp(selectraise, "on")))
+                    evas_object_raise(it->base.view);
+                  evas_object_smart_callback_call((void *)obj, "changed", (void *)it->base.data);
+                  if (wd->delay) ecore_timer_del(wd->delay);
+                  wd->delay = ecore_timer_add(0.2, _delay_change, obj);
+               }
+          }
+        if (it_closest)
+          {
+             it = it_closest;
+             if (!last)
+               last = strdup(it->letter);
+             else
+               {
+                  if (!label) label = strdup(last);
+                  else
+                    {
+                       /* FIXME: realloc return NULL if the request fails */
+                       label = realloc(label, strlen(label) + strlen(last) + 1);
+                       strcat(label, last);
+                    }
+                  free(last);
+                  last = strdup(it->letter);
+               }
+          }
+     }
+   if (!label) label = strdup("");
+   if (!last) last = strdup("");
+   edje_object_part_text_set(wd->base, "elm.text.body", label);
+   edje_object_part_text_set(wd->base, "elm.text", last);
+   free(label);
+   free(last);
+}
+
+static void 
+_wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+//   Evas_Event_Mouse_Wheel *ev = event_info;
+//   Evas_Object *obj = o;
+   if (!wd) return;
+}
+
+static void 
+_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord x, y;
+   if (!wd) return;
+   if (ev->button != 1) return;
+   wd->down = 1;
+   evas_object_geometry_get(wd->base, &x, &y, NULL, NULL);
+   wd->dx = ev->canvas.x - x;
+   wd->dy = ev->canvas.y - y;
+   elm_index_active_set(data, 1);
+   _sel_eval(data, ev->canvas.x, ev->canvas.y);
+   edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer", 
+                                   wd->dx, wd->dy);
+}
+
+static void 
+_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Up *ev = event_info;
+   void *d;
+   if (!wd) return;
+   if (ev->button != 1) return;
+   wd->down = 0;
+   d = (void *)elm_index_item_selected_get(data, wd->level);
+   if (d) evas_object_smart_callback_call(data, "selected", d);
+   elm_index_active_set(data, 0);
+   edje_object_signal_emit(wd->base, "elm,state,level,0", "elm");
+}
+
+static void 
+_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Coord minw = 0, minh = 0, x, y, dx, adx;
+   char buf[1024];
+   if (!wd) return;
+   if (!wd->down) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_geometry_get(wd->base, &x, &y, NULL, NULL);
+   x = ev->cur.canvas.x - x;
+   y = ev->cur.canvas.y - y;
+   dx = x - wd->dx;
+   adx = dx;
+   if (adx < 0) adx = -dx;
+   edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer", x, y);
+   if (!wd->horizontal)
+     {
+        if (adx > minw)
+          {
+             if (!wd->level)
+               { 
+                  wd->level = 1;
+                  snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
+                  edje_object_signal_emit(wd->base, buf, "elm");
+                  evas_object_smart_callback_call(data, "level,up", NULL);
+               }
+          }
+        else
+          {
+             if (wd->level == 1)
+               {
+                  wd->level = 0;
+                  snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
+                  edje_object_signal_emit(wd->base, buf, "elm");
+                  evas_object_smart_callback_call(data, "level,down", NULL);
+               }
+          }
+     }
+   _sel_eval(data, ev->cur.canvas.x, ev->cur.canvas.y);
+}
+
+/**
+ * Add a new index to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Index
+ */
+EAPI Evas_Object *
+elm_index_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas_Object *o;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord minw, minh;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "index");
+   elm_widget_type_set(obj, "index");
+   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);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->horizontal = EINA_FALSE;
+
+   wd->base = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->base, "index", "base/vertical", "default");
+   elm_widget_resize_object_set(obj, wd->base);
+
+   o = evas_object_rectangle_add(e);
+   wd->event[0] = o;
+   evas_object_color_set(o, 0, 0, 0, 0);
+   minw = minh = 0;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_size_hint_min_set(o, minw, minh);
+   edje_object_part_swallow(wd->base, "elm.swallow.event.0", o);
+   elm_widget_sub_object_add(obj, o);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _wheel, obj);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, obj);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _mouse_up, obj);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, obj);
+   evas_object_show(o);
+   if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
+     {
+        o = evas_object_rectangle_add(e);
+        wd->event[1] = o;
+        evas_object_color_set(o, 0, 0, 0, 0);
+        evas_object_size_hint_min_set(o, minw, minh);
+        edje_object_part_swallow(wd->base, "elm.swallow.event.1", o);
+        elm_widget_sub_object_add(obj, o);
+     }
+
+   wd->bx[0] = evas_object_box_add(e);
+   evas_object_box_layout_set(wd->bx[0], _layout, wd, NULL);
+   elm_widget_sub_object_add(obj, wd->bx[0]);
+   edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
+   evas_object_show(wd->bx[0]);
+
+   if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
+     {
+        wd->bx[1] = evas_object_box_add(e);
+       evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
+        elm_widget_sub_object_add(obj, wd->bx[1]);
+        edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
+        evas_object_show(wd->bx[1]);
+     }
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the active state of the index programatically
+ *
+ * @param obj The index object
+ * @param active The active starte
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_active_set(Evas_Object *obj, Eina_Bool active)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->active == active) return;
+   wd->active = active;
+   wd->level = 0;
+   if (wd->active)
+     {
+        _index_box_clear(obj, wd->bx[1], 1);
+        _index_box_auto_fill(obj, wd->bx[0], 0);
+        edje_object_signal_emit(wd->base, "elm,state,active", "elm");
+     }
+   else
+     edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
+}
+
+/**
+ * Sets the level of the item.
+ *
+ * @param obj The index object.
+ * @param level To be documented.
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_level_set(Evas_Object *obj, int level)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->level == level) return;
+   wd->level = level;
+}
+
+/**
+ * Gets the level of the item.
+ *
+ * @param obj The index object
+ *
+ * @ingroup Index
+ */
+EAPI int
+elm_index_item_level_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->level;
+}
+
+/**
+ * Returns the selected item.
+ *
+ * @param obj The index object.
+ * @param level to be documented.
+ *
+ * @ingroup Index
+ */
+EAPI void *
+elm_index_item_selected_get(const Evas_Object *obj, int level)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Elm_Index_Item *it;
+   if (!wd) return NULL;
+   EINA_LIST_FOREACH(wd->items, l, it)
+     if ((it->selected) && (it->level == level))
+       return elm_widget_item_data_get(it);
+   return NULL;
+}
+
+/**
+ * Appends a new item.
+ *
+ * @param obj The index object.
+ * @param letter Letter under which the item should be indexed
+ * @param item The item to put in the index
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_append(Evas_Object *obj, const char *letter, const void *item)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it;
+   if (!wd) return;
+   it = _item_new(obj, letter, item);
+   if (!it) return;
+   wd->items = eina_list_append(wd->items, it);
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+}
+
+/**
+ * Prepends a new item.
+ *
+ * @param obj The index object.
+ * @param letter Letter under which the item should be indexed
+ * @param item The item to put in the index
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it;
+
+   if (!wd) return;
+   it = _item_new(obj, letter, item);
+   if (!it) return;
+   wd->items = eina_list_prepend(wd->items, it);
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+}
+
+/**
+ * Append an item after @p relative in letter @p letter.
+ *
+ * @param obj The index object
+ * @param letter Letter under which the item should be indexed
+ * @param item The item to put in the index
+ * @param relative The item to put @p item after
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it, *it_rel;
+   if (!wd) return;
+   if (!relative)
+     {
+        elm_index_item_append(obj, letter, item);
+        return;
+     }
+   it = _item_new(obj, letter, item);
+   it_rel = _item_find(obj, relative);
+   if (!it_rel)
+     {
+        elm_index_item_append(obj, letter, item);
+        return;
+     }
+   if (!it) return;
+   wd->items = eina_list_append_relative(wd->items, it, it_rel);
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+}
+
+/**
+ * Prepend an item before @p relative in letter @p letter.
+ *
+ * @param obj The index object
+ * @param letter Letter under which the item should be indexed
+ * @param item The item to put in the index
+ * @param relative The item to put @p item before
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it, *it_rel;
+   if (!wd) return;
+   if (!relative)
+     {
+        elm_index_item_prepend(obj, letter, item);
+        return;
+     }
+   it = _item_new(obj, letter, item);
+   it_rel = _item_find(obj, relative);
+   if (!it_rel)
+     {
+        elm_index_item_append(obj, letter, item);
+        return;
+     }
+   if (!it) return;
+   wd->items = eina_list_prepend_relative(wd->items, it, it_rel);
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+}
+
+/**
+ * Insert a new @p item into the sorted index @p obj in @p letter.
+ *
+ * @param obj The index object
+ * @param letter Letter under which the item should be indexed
+ * @param item The item to put in the index
+ * @param cmp_func The function called for the sort of index items.
+ * @param cmp_data_func The function called for the sort of the data. It will
+ * be used when cmp_func return 0. It means the index item already exists.
+ * So, to decide which data item should be pointed by the index item, a function
+ * to compare them is needed. If this function is not provided, index items
+ * will be duplicated. If cmp_data_func returns a non-negative value, the
+ * previous index item data will be replaced by the inserted @p item. So
+ * if the previous data need to be free, it should be done in this function,
+ * because the reference will be lost.
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, const void *item, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *lnear;
+   Elm_Index_Item *it;
+   int cmp;
+
+   if (!wd) return;
+   if (!(wd->items))
+     {
+        elm_index_item_append(obj, letter, item);
+        return;
+     }
+
+   it = _item_new(obj, letter, item);
+   if (!it) return;
+
+   lnear = eina_list_search_sorted_near_list(wd->items, cmp_func, it, &cmp);
+   if (cmp < 0)
+     wd->items =  eina_list_append_relative_list(wd->items, it, lnear);
+   else if (cmp > 0)
+     wd->items = eina_list_prepend_relative_list(wd->items, it, lnear);
+   else
+     {
+       /* If cmp_data_func is not provided, append a duplicated item */
+       if (!cmp_data_func)
+         wd->items =  eina_list_append_relative_list(wd->items, it, lnear);
+       else
+         {
+            Elm_Index_Item *p_it = eina_list_data_get(lnear);
+            if (cmp_data_func(p_it->base.data, it->base.data) >= 0)
+              p_it->base.data = it->base.data;
+            _item_free(it);
+         }
+     }
+
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+}
+
+/**
+ * Remove an item from the index.
+ *
+ * @param obj The index object
+ * @param item The item to remove from the index
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_del(Evas_Object *obj, const void *item)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it;
+   if (!wd) return;
+   it = _item_find(obj, item);
+   if (!it) return;
+   _item_free(it);
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+}
+
+/**
+ * Find an index item using item data.
+ *
+ * @param obj The index object
+ * @param item The item pointed by index item
+ * @return The index item pointing to @p item
+ *
+ * @ingroup Index
+ */
+EAPI Elm_Index_Item *
+elm_index_item_find(Evas_Object *obj, const void *item)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return _item_find(obj, item);
+}
+
+/**
+ * Clears an index of its items.
+ *
+ * @param obj The index object.
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Index_Item *it;
+   Eina_List *l, *clear = NULL;
+   if (!wd) return;
+   _index_box_clear(obj, wd->bx[wd->level], wd->level);
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+        if (it->level != wd->level) continue;
+        clear = eina_list_append(clear, it);
+     }
+   EINA_LIST_FREE(clear, it) _item_free(it);
+}
+
+/**
+ * Go to item at @p level
+ *
+ * @param obj The index object
+ * @param level The index level
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_go(Evas_Object *obj, int level __UNUSED__)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _index_box_auto_fill(obj, wd->bx[0], 0);
+   if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
+}
+
+/**
+ * Returns the data associated with the item.
+ *
+ * @param it The list item
+ * @return The data associated with @p it
+ *
+ * @ingroup Index
+ */
+EAPI void *
+elm_index_item_data_get(const Elm_Index_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   return elm_widget_item_data_get(it);
+}
+
+/**
+ * Set the data item from the index item
+ *
+ * This set a new data value.
+ *
+ * @param it The item
+ * @param data The new data pointer to set
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_data_set(Elm_Index_Item *it, const void *data)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   elm_widget_item_data_set(it, data);
+}
+
+/**
+ * Set the function called when a index item is freed.
+ *
+ * @param it The item to set the callback on
+ * @param func The function called
+ *
+ * @ingroup Index
+ */
+EAPI void
+elm_index_item_del_cb_set(Elm_Index_Item *it, Evas_Smart_Cb func)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   elm_widget_item_del_cb_set(it, func);
+}
+
+/**
+ * Gets the letter of the item.
+ *
+ * @param it The list item
+ * @return The letter of @p it
+ *
+ * @ingroup Index
+ */
+EAPI const char *
+elm_index_item_letter_get(const Elm_Index_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   return it->letter;
+}
+
diff --git a/src/lib/elm_label.c b/src/lib/elm_label.c
new file mode 100644 (file)
index 0000000..5240cec
--- /dev/null
@@ -0,0 +1,1064 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Label Label
+ *
+ * Display text, with simple html-like markup. The theme of course
+ * can invent new markup tags and style them any way it likes
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *lbl;
+   Evas_Object *bg;
+   const char *label;
+   Ecore_Job *deferred_recalc_job;
+   double slide_duration;
+   Evas_Coord lastw;
+   Evas_Coord wrap_w;
+   Evas_Coord wrap_h;
+   Eina_Bool linewrap : 1;
+   Eina_Bool changed : 1;
+   Eina_Bool bgcolor : 1;
+   Eina_Bool ellipsis : 1;
+   Eina_Bool slidingmode : 1;
+   Eina_Bool slidingellipsis : 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 int _get_value_in_key_string(const char *oldstring, const char *key, char **value);
+static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag);
+static int _stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag);
+static int _is_width_over(Evas_Object *obj, Eina_Bool multiline);
+static void _ellipsis_label_to_width(Evas_Object *obj, Eina_Bool multiline);
+static void _label_sliding_change(Evas_Object *obj);
+
+static void
+_elm_win_recalc_job(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord minw = -1, minh = -1, maxh = -1;
+   Evas_Coord resw, resh, minminw;
+   if (!wd) return;
+   wd->deferred_recalc_job = NULL;
+   evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
+   resh = 0;
+   edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, 0, 0);
+   minminw = minw;
+   if (wd->wrap_w >= resw) 
+     {
+        resw = wd->wrap_w;
+        edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
+        evas_object_size_hint_min_set(data, minw, minh);
+     }
+   else
+     {
+        if (wd->wrap_w > minminw) minminw = wd->wrap_w;
+        edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
+        evas_object_size_hint_min_set(data, minminw, minh);
+     }
+
+   if ((wd->ellipsis) && (wd->linewrap) && (wd->wrap_h > 0) && 
+       (_is_width_over(data, 1) == 1))
+     _ellipsis_label_to_width(data, 1);
+
+   maxh = minh;
+   evas_object_size_hint_max_set(data, -1, maxh);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
+   if (wd->label) eina_stringshare_del(wd->label);
+   if (wd->bg) evas_object_del(wd->bg);
+   free(wd);
+}
+
+static void
+_theme_change(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->linewrap)
+     {
+        if (wd->ellipsis)
+          _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap_ellipsis", 
+                                elm_widget_style_get(obj));
+        else
+          _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap", 
+                                elm_widget_style_get(obj));
+     }
+   else
+     _elm_theme_object_set(obj, wd->lbl, "label", "base", 
+                           elm_widget_style_get(obj));
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _theme_change(obj);
+   edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+   edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) * 
+                         _elm_config->scale);
+   _label_sliding_change(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;
+   Evas_Coord resw, resh;
+   if (!wd) return;
+   if (wd->linewrap)
+     {
+        evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
+        if ((resw == wd->lastw) && (!wd->changed)) return;
+        wd->changed = EINA_FALSE;
+        wd->lastw = resw;
+        _elm_win_recalc_job(obj);
+// FIXME: works ok. but NOT for genlist. what should genlist do?        
+//        if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
+//        wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
+     }
+   else
+     {
+        evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
+        edje_object_size_min_calc(wd->lbl, &minw, &minh);
+        if (wd->wrap_w > 0 && minw > wd->wrap_w) minw = wd->wrap_w;
+        evas_object_size_hint_min_set(obj, minw, minh);
+        maxh = minh;
+        evas_object_size_hint_max_set(obj, maxw, maxh);
+        if ((wd->ellipsis) && (_is_width_over(obj, 0) == 1))
+           _ellipsis_label_to_width(obj, 0);
+     }
+}
+
+static void 
+_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->linewrap) _sizing_eval(data);
+}
+
+static int
+_get_value_in_key_string(const char *oldstring, const char *key, char **value)
+{
+   char *curlocater, *starttag, *endtag;
+   int firstindex = 0, foundflag = -1;
+   
+   curlocater = strstr(oldstring, key);
+   if (curlocater)
+     {
+        int key_len = strlen(key);
+        starttag = curlocater;
+        endtag = curlocater + key_len;
+        if ((!endtag) || (*endtag != '='))
+          {
+             foundflag = 0;
+             return -1;
+          }
+        firstindex = abs(oldstring - curlocater);
+        firstindex += key_len + 1; // strlen("key") + strlen("=")
+        *value = (char *)oldstring + firstindex;
+        
+        while (oldstring != starttag)
+          {
+             if (*starttag == '>')
+               {
+                  foundflag = 0;
+                  break;
+               }
+             if (*starttag == '<') 
+               break;
+             else 
+               starttag--;
+             if (!starttag) break;
+          }
+        
+        while (endtag)
+          {
+             if (*endtag == '<')
+               {
+                  foundflag = 0;
+                  break;
+               }
+             if (*endtag == '>') 
+               break;
+             else 
+               endtag++;
+             if (!endtag) break;
+          }
+        
+        if ((foundflag) && (*starttag == '<') && (*endtag == '>'))
+          foundflag = 1;
+        else 
+          foundflag = 0;
+     }
+   else
+     {
+        foundflag = 0;
+     }
+   
+   if (foundflag == 1) return 0;
+   
+   return -1;
+}
+
+
+static int
+_strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag)
+{
+   const char *srcstring = NULL;
+   Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
+   char *curlocater, *replocater;
+   char *starttag, *endtag;
+   int tagtxtlen = 0, insertflag = 0;
+   
+   srcstring = eina_strbuf_string_get(srcbuf);
+   curlocater = strstr(srcstring, key);
+   
+   if (!curlocater)
+     insertflag = 1;
+   else
+     {
+        int key_len = strlen(key);
+        do 
+          {
+             starttag = strchr(srcstring, '<');
+             endtag = strchr(srcstring, '>');
+             tagtxtlen = endtag - starttag;
+             if (tagtxtlen <= 0) tagtxtlen = 0;
+             if ((starttag < curlocater) && (curlocater < endtag)) break;
+             if ((endtag) && ((endtag + 1)))
+               srcstring = endtag + 1;
+             else
+               break;
+          } while (strlen(srcstring) > 1);
+        
+        if ((starttag) && (endtag) && (tagtxtlen > key_len))
+          {
+             repbuf = eina_strbuf_new();
+             diffbuf = eina_strbuf_new();
+             eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
+             srcstring = eina_strbuf_string_get(repbuf);
+             curlocater = strstr(srcstring, key);
+             if (curlocater)
+               {
+                  replocater = curlocater + key_len + 1;
+                  while ((*replocater != '=') && (replocater))
+                    replocater++;
+
+                  while ((*replocater) && 
+                         (*replocater != ' ') && 
+                         (*replocater != '>'))
+                    replocater++;
+
+                  if ((replocater - curlocater) > (key_len + 1))
+                    {
+                       replocater--;
+                       eina_strbuf_append_n(diffbuf, curlocater, 
+                                            replocater-curlocater);
+                    }
+                  else
+                    insertflag = 1;
+               }
+             else
+               insertflag = 1;
+             eina_strbuf_reset(repbuf);
+          }
+        else
+          insertflag = 1; 
+     }
+   
+   if (!repbuf) repbuf = eina_strbuf_new();
+   if (!diffbuf) diffbuf = eina_strbuf_new();
+   
+   if (insertflag)
+     {
+        eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
+        eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
+     }
+   else
+     {
+        if (deleteflag)
+          {
+             eina_strbuf_prepend(diffbuf, "<");
+             eina_strbuf_append(diffbuf, ">");
+             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
+          }
+        else
+          {
+             eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
+             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
+          }
+     }
+
+   if (repbuf) eina_strbuf_free(repbuf);
+   if (diffbuf) eina_strbuf_free(diffbuf);
+  
+   return 0;           
+}
+
+static int
+_stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag)
+{
+   Eina_Strbuf *sharebuf = NULL;   
+   
+   sharebuf = eina_strbuf_new();
+   eina_strbuf_append(sharebuf, *srcstring);
+   _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
+   eina_stringshare_del(*srcstring);
+   *srcstring = eina_stringshare_add(eina_strbuf_string_get(sharebuf));
+   eina_strbuf_free(sharebuf);
+
+   return 0;
+}
+
+static int
+_is_width_over(Evas_Object *obj, Eina_Bool multiline)
+{
+   Evas_Coord x, y, w, h;
+   Evas_Coord vx, vy, vw, vh;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   const char *ellipsis_string = "...";
+   int mincount = sizeof(ellipsis_string) - 1;
+   char *plaintxt;
+   int plainlen = 0;
+
+   plaintxt = _elm_util_mkup_to_text(edje_object_part_text_get(wd->lbl, "elm.text"));
+   if (plaintxt)
+     {
+        plainlen = strlen(plaintxt);
+        free(plaintxt);
+     }
+   // too short to ellipsis
+   if (plainlen <= mincount) return 0;
+
+   edje_object_part_geometry_get(wd->lbl, "elm.text", &x, &y, &w, &h);
+   evas_object_geometry_get(obj, &vx, &vy, &vw, &vh);
+
+   if (!multiline) // single line
+     {
+        // skip if too early to check widget size
+        if ((w < 0) && (h < 0)) return 0;
+        // if string fits at widget
+        if ((x >= 0) && (y >= 0))
+          {
+             if ((wd->wrap_w > 0) && (wd->wrap_w < w))
+               {
+                  Evas_Coord minw, minh;
+                  
+                  edje_object_size_min_calc(wd->lbl, &minw, &minh);
+                  if (minw < wd->wrap_w) return 0; // min insufficient
+                  else return 1;
+               }
+             else return 0;
+          }
+        if ((0 < wd->wrap_w) && (w > wd->wrap_w)) return 1;
+     }
+   else // multiline
+     {
+        if (((x >= 0) || (y >= 0)) && (h > wd->wrap_h)) return 1;
+     }
+   
+   return 0;
+}
+
+static void
+_ellipsis_fontsize_set(Evas_Object *obj, int fontsize)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   Eina_Strbuf *fontbuf = NULL;
+   Eina_Strbuf *txtbuf = NULL;
+   txtbuf = eina_strbuf_new();
+   fontbuf = eina_strbuf_new();
+   eina_strbuf_append(txtbuf, edje_object_part_text_get(wd->lbl, "elm.text"));
+   eina_strbuf_append_printf(fontbuf, "%d", fontsize);
+   _strbuf_key_value_replace(txtbuf, "font_size", eina_strbuf_string_get(fontbuf), 0);
+   edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
+   eina_strbuf_free(fontbuf);
+   eina_strbuf_free(txtbuf);
+}
+
+static Eina_Bool
+_ellipsis_cut_chars_to_widget(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   const char *ellipsis_string = "...";
+   int mincount = sizeof(ellipsis_string) - 1; 
+   Evas_Coord w, h;
+   Evas_Textblock_Cursor *tc1, *tc2;
+   char *cutstr, *elstr;
+   int limitw = 0;
+   int lencutstr = 0;
+   int i = 0;
+
+   edje_object_part_geometry_get(wd->lbl, "elm.text", NULL, NULL, &w, &h);
+   if (w <= 0) return EINA_FALSE;
+   tc1 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+   tc2 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+
+   if ((wd->wrap_w > 0) && (wd->wrap_w < w)) limitw = wd->wrap_w;
+   else limitw = w;
+   evas_textblock_cursor_pos_set(tc1, 0);
+   evas_textblock_cursor_char_coord_set(tc2, limitw, 0);
+
+   // if too small to cut,(is it bug? or any other reasons?)
+   // then fallback to one step mode
+   if (evas_textblock_cursor_pos_get(tc2) < mincount)
+     {
+        Evas_Coord cx, cy, cw, ch;
+        int eolpos = evas_textblock_cursor_paragraph_text_length_get(tc1);
+        
+        for (i = eolpos; i > mincount; i--)
+          {
+             evas_textblock_cursor_pos_set(tc2, i);
+             evas_textblock_cursor_char_geometry_get(tc2, &cx, &cy, &cw, &ch);
+             if (cx <= limitw) break;
+          }
+
+        if (evas_textblock_cursor_pos_get(tc2) < mincount)
+          {
+             evas_textblock_cursor_free(tc1);
+             evas_textblock_cursor_free(tc2);
+             return EINA_FALSE;
+          }
+     }
+
+   for (i = 0; i <= mincount; i++) evas_textblock_cursor_char_prev(tc2);
+   cutstr = evas_textblock_cursor_range_text_get(tc1, tc2, EVAS_TEXTBLOCK_TEXT_PLAIN);
+   if (!cutstr) return EINA_FALSE;
+   
+   lencutstr = strlen(cutstr);
+   elstr = alloca(sizeof(char) * (lencutstr + mincount + 1));
+   strcpy(elstr, cutstr);
+   free(cutstr);
+   strcat(elstr, ellipsis_string);
+   edje_object_part_text_set(wd->lbl, "elm.text", elstr);
+
+   evas_textblock_cursor_free(tc1);
+   evas_textblock_cursor_free(tc2);
+   
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_ellipsis_cut_lines_to_widget(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   const char *ellipsis_string = "...";
+   int mincount = sizeof(ellipsis_string) - 1; 
+   Evas_Coord w, h;
+   Evas_Textblock_Cursor *tc1, *tc2;
+   int linenum = 0, cutline = 0;
+   double lineheight = 0.0;
+   char *cutstr, *elstr;
+   int lencutstr = 0;
+   int limith = 0;
+   int i;
+
+   edje_object_part_geometry_get(wd->lbl, "elm.text", NULL, NULL, &w, &h);
+
+   tc1 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+   tc2 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+   // goto last paragraph
+   while (evas_textblock_cursor_paragraph_next(tc2) == EINA_TRUE);
+   
+   evas_textblock_cursor_paragraph_last(tc2);
+   // get total linenumber
+   linenum = evas_textblock_cursor_line_geometry_get(tc2, NULL, NULL, NULL, NULL);
+   lineheight = (double)h / (double)linenum;
+   if ((wd->wrap_h > 0) && (wd->wrap_h < h)) limith = wd->wrap_h;
+   else limith = h;
+   cutline = limith / lineheight;
+   if (cutline < 1) cutline = 1;
+   
+   evas_textblock_cursor_pos_set(tc1, 0);
+   evas_textblock_cursor_line_set(tc2, cutline - 1);
+   evas_textblock_cursor_line_char_last(tc2);
+   for (i = 0; i <= mincount; i++) evas_textblock_cursor_char_prev(tc2);
+   cutstr = evas_textblock_cursor_range_text_get(tc1, tc2, EVAS_TEXTBLOCK_TEXT_PLAIN);
+   if (!cutstr) return EINA_FALSE;
+   
+   lencutstr = strlen(cutstr);
+   elstr = alloca(sizeof(char) * (lencutstr + mincount + 1));
+   strcpy(elstr, cutstr);
+   free(cutstr);
+   strcat(elstr, ellipsis_string);
+   edje_object_part_text_set(wd->lbl, "elm.text", elstr);
+
+   evas_textblock_cursor_free(tc1);
+   evas_textblock_cursor_free(tc2);
+
+   return EINA_TRUE;
+}
+
+static void
+_ellipsis_label_to_width(Evas_Object *obj, Eina_Bool multiline)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   int cur_fontsize = 0;
+   char *kvalue;
+   const char *minfont, *deffont, *maxfont;
+   int minfontsize, maxfontsize;
+
+   minfont = edje_object_data_get(wd->lbl, "min_font_size");
+   if (minfont) minfontsize = atoi(minfont);
+   else minfontsize = 1;
+   maxfont = edje_object_data_get(wd->lbl, "max_font_size");
+   if (maxfont) maxfontsize = atoi(maxfont);
+   else maxfontsize = 1;
+   deffont = edje_object_data_get(wd->lbl, "default_font_size");
+   if (deffont) cur_fontsize = atoi(deffont);
+   else cur_fontsize = 1;
+   if (minfontsize > maxfontsize || cur_fontsize == 1) return;  // theme is not ready for ellipsis
+   if (eina_stringshare_strlen(wd->label) <= 0) return;
+   
+   if (_get_value_in_key_string(wd->label, "font_size", &kvalue) == 0)
+     {
+        if (kvalue != NULL) cur_fontsize = atoi(kvalue);
+     }
+   
+   while (_is_width_over(obj, multiline))
+     {
+        if (cur_fontsize > minfontsize)
+          {
+             cur_fontsize -= 3;
+             if (cur_fontsize < minfontsize) cur_fontsize = minfontsize;
+             _ellipsis_fontsize_set(obj, cur_fontsize);
+          }
+        else
+          {
+             if (!multiline) // single line
+               {
+                  _ellipsis_cut_chars_to_widget(obj);
+                  break;
+               }
+             else // multiline
+               {
+                  _ellipsis_cut_lines_to_widget(obj);
+                  break;
+               }
+          }
+     }
+}
+
+static void
+_label_sliding_change(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   char *plaintxt;
+   int plainlen = 0;
+   
+   // dosen't support multiline sliding effect
+   if (wd->linewrap)
+     { 
+        wd->slidingmode = EINA_FALSE;
+        return;
+     }
+
+   plaintxt = _elm_util_mkup_to_text(edje_object_part_text_get(wd->lbl, "elm.text"));
+   if (plaintxt != NULL)
+     {
+        plainlen = strlen(plaintxt);
+        free(plaintxt);
+     }
+   // too short to slide label
+   if (plainlen < 1)
+     {
+        wd->slidingmode = EINA_TRUE;
+        return;
+     }
+
+   if (wd->slidingmode)
+     {
+        Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
+        
+        if (wd->ellipsis)
+          {
+             wd->slidingellipsis = EINA_TRUE;
+             elm_label_ellipsis_set(obj, EINA_FALSE);
+          }
+        
+        msg->count = 1;
+        msg->val[0] = wd->slide_duration;
+
+        edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
+        edje_object_signal_emit(wd->lbl, "elm,state,slide,start", "elm");
+     }
+   else
+     {
+        edje_object_signal_emit(wd->lbl, "elm,state,slide,stop", "elm");
+        if (wd->slidingellipsis)
+          {
+             wd->slidingellipsis = EINA_FALSE;
+             elm_label_ellipsis_set(obj, EINA_TRUE);
+          }
+     }
+}
+
+/**
+ * Add a new label to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Label
+ */
+EAPI Evas_Object *
+elm_label_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   wd->bgcolor = EINA_FALSE;
+   wd->bg = evas_object_rectangle_add(e);
+   evas_object_color_set(wd->bg, 0, 0, 0, 0);
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "label");
+   elm_widget_type_set(obj, "label");
+   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, EINA_FALSE);
+
+   wd->linewrap = EINA_FALSE;
+   wd->ellipsis = EINA_FALSE;
+   wd->slidingmode = EINA_FALSE;
+   wd->slidingellipsis = EINA_FALSE;
+   wd->wrap_w = 0;
+   wd->wrap_h = 0;
+   wd->slide_duration = 10;
+
+   wd->lbl = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
+   wd->label = eina_stringshare_add("<br>");
+   edje_object_part_text_set(wd->lbl, "elm.text", "<br>");
+   elm_widget_resize_object_set(obj, wd->lbl);
+   
+   evas_object_event_callback_add(wd->lbl, EVAS_CALLBACK_RESIZE, _resize, obj);
+   
+   wd->changed = 1;
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the label on the label object
+ *
+ * @param obj The label object
+ * @param label The label will be used on the label object
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_label_set(Evas_Object *obj, const char *label)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (!label) label = "";
+   eina_stringshare_replace(&wd->label, label);
+   edje_object_part_text_set(wd->lbl, "elm.text", label);
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the label used on the label object
+ *
+ * @param obj The label object
+ * @return The string inside the label
+ * @ingroup Label
+ */
+EAPI const char *
+elm_label_label_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->label;
+}
+
+/**
+ * Set the wrapping behavior of the label
+ *
+ * @param obj The label object
+ * @param wrap To wrap text or not
+ * @ingroup Label
+ */
+EAPI void
+elm_label_line_wrap_set(Evas_Object *obj, Eina_Bool wrap)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   const char *t;
+   if (wd->linewrap == wrap) return;
+   wd->linewrap = wrap;
+   t = eina_stringshare_add(elm_label_label_get(obj));
+   _theme_change(obj);
+   elm_label_label_set(obj, t);
+   eina_stringshare_del(t);
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the wrapping behavior of the label
+ *
+ * @param obj The label object
+ * @return To wrap text or not
+ * @ingroup Label
+ */
+EAPI Eina_Bool
+elm_label_line_wrap_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->linewrap;
+}
+
+/**
+ * Set wrap width of the label
+ *
+ * @param obj The label object
+ * @param w The wrap width in pixels at a minimum where words need to wrap
+ * @ingroup Label
+ */
+EAPI void
+elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (w < 0) w = 0;
+   if (wd->wrap_w == w) return;
+   if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+   wd->wrap_w = w;
+   _sizing_eval(obj);
+}
+
+/**
+ * get wrap width of the label
+ *
+ * @param obj The label object
+ * @return The wrap width in pixels at a minimum where words need to wrap
+ * @ingroup Label
+ */
+EAPI Evas_Coord
+elm_label_wrap_width_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->wrap_w;
+}
+
+/**
+ * Set wrap height of the label
+ *
+ * @param obj The label object
+ * @param w The wrap width in pixels at a minimum where words need to wrap
+ * @ingroup Label
+ */
+EAPI void
+elm_label_wrap_height_set(Evas_Object *obj,
+                          Evas_Coord   h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (h < 0) h = 0;
+   if (wd->wrap_h == h) return;
+   if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+   wd->wrap_h = h;
+   _sizing_eval(obj);
+}
+
+/**
+ * get wrap width of the label
+ *
+ * @param obj The label object
+ * @return The wrap height in pixels at a minimum where words need to wrap
+ * @ingroup Label
+ */
+EAPI Evas_Coord
+elm_label_wrap_height_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->wrap_h;
+}
+
+/**
+ * Set the font size on the label object.
+ * 
+ * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
+ * "big", "medium", "small" - or better name them by use:
+ * "title", "footnote", "quote" etc.
+ *
+ * @param obj The label object
+ * @param size font size
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_fontsize_set(Evas_Object *obj, int fontsize)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Strbuf *fontbuf = NULL;
+   int len, removeflag = 0;
+
+   if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
+   len = strlen(wd->label);
+   if (len <= 0) return;
+   fontbuf = eina_strbuf_new();
+   eina_strbuf_append_printf(fontbuf, "%d", fontsize);
+
+   if (fontsize == 0) removeflag = 1;  // remove fontsize tag
+
+   if (_stringshare_key_value_replace(&wd->label, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+        wd->changed = 1;
+        _sizing_eval(obj);
+     }
+   eina_strbuf_free(fontbuf);
+}
+
+/**
+ * Set the text align on the label object
+ *
+ * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
+ * "big", "medium", "small" - or better name them by use:
+ * "title", "footnote", "quote" etc.
+ *
+ * @param obj The label object
+ * @param align align mode ("left", "center", "right")
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_text_align_set(Evas_Object *obj, const char *alignmode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int len;
+
+   if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
+   len = strlen(wd->label);
+   if (len <= 0) return;
+
+   if (_stringshare_key_value_replace(&wd->label, "align", alignmode, 0) == 0)
+     edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
+/**
+ * Set the text color on the label object
+ *
+ * @param obj The label object
+ * @param r Red property background color of The label object
+ * @param g Green property background color of The label object
+ * @param b Blue property background color of The label object
+ * @param a Alpha property background color of The label object
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_text_color_set(Evas_Object *obj,
+                         unsigned int r,
+                         unsigned int g,
+                         unsigned int b,
+                         unsigned int a)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Strbuf *colorbuf = NULL;
+   int len;
+
+   if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
+   len = strlen(wd->label);
+   if (len <= 0) return;
+   colorbuf = eina_strbuf_new();
+   eina_strbuf_append_printf(colorbuf, "#%02X%02X%02X%02X", r, g, b, a);
+
+   if (_stringshare_key_value_replace(&wd->label, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
+     {
+        edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+        wd->changed = 1;
+        _sizing_eval(obj);
+     }
+   eina_strbuf_free(colorbuf);
+}
+
+/**
+ * Set background color of the label
+ *
+ * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
+ * "big", "medium", "small" - or better name them by use:
+ * "title", "footnote", "quote" etc.
+ *
+ * @param obj The label object
+ * @param r Red property background color of The label object 
+ * @param g Green property background color of The label object 
+ * @param b Blue property background color of The label object 
+ * @param a Alpha property background alpha of The label object 
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_background_color_set(Evas_Object *obj,
+                               unsigned int r,
+                               unsigned int g,
+                               unsigned int b,
+                               unsigned int a)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_color_set(wd->bg, r, g, b, a);
+
+   if (!wd) return;
+   _elm_dangerous_call_check(__FUNCTION__);
+   if (wd->bgcolor == EINA_FALSE)
+     {
+        wd->bgcolor = 1;
+        edje_object_part_swallow(wd->lbl, "label.swallow.background", wd->bg);
+     }
+}
+
+/**
+ * Set the ellipsis behavior of the label
+ *
+ * @param obj The label object
+ * @param ellipsis To ellipsis text or not
+ * @ingroup Label
+ */
+EAPI void
+elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->ellipsis == ellipsis) return;
+   wd->ellipsis = ellipsis;
+   if (wd->linewrap) _theme_change(obj);
+   edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
+/**
+ * Set the text slide of the label
+ *
+ * @param obj The label object
+ * @param slide To start slide or stop
+ * @ingroup Label
+ */
+EAPI void
+elm_label_slide_set(Evas_Object *obj,
+                    Eina_Bool    slide)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->slidingmode == slide) return;
+   wd->slidingmode = slide;
+   _label_sliding_change(obj);
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
+/**
+ * get the text slide mode of the label
+ *
+ * @param obj The label object
+ * @return slide slide mode value
+ * @ingroup Label
+ */
+EAPI Eina_Bool
+elm_label_slide_get(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->slidingmode;
+}
+
+/**
+ * set the slide duration(speed) of the label
+ *
+ * @param obj The label object
+ * @return The duration time in moving text from slide begin position to slide end position
+ * @ingroup Label
+ */
+EAPI void
+elm_label_slide_duration_set(Evas_Object *obj, double duration)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
+
+   if (!wd) return;
+   wd->slide_duration = duration;
+   msg->count = 1;
+   msg->val[0] = wd->slide_duration;
+   edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
+}
+
+/**
+ * get the slide duration(speed) of the label
+ *
+ * @param obj The label object
+ * @return The duration time in moving text from slide begin position to slide end position
+ * @ingroup Label
+ */
+EAPI double
+elm_label_slide_duration_get(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->slide_duration;
+}
+
diff --git a/src/lib/elm_layout.c b/src/lib/elm_layout.c
new file mode 100644 (file)
index 0000000..a398af4
--- /dev/null
@@ -0,0 +1,1274 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Layout Layout
+ *
+ * This takes a standard Edje design file and wraps it very thinly
+ * in a widget and handles swallowing widgets into swallow regions
+ * in the Edje object, allowing Edje to be used as a design and
+ * layout tool
+ */
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Subinfo Subinfo;
+typedef struct _Part_Cursor Part_Cursor;
+
+struct _Widget_Data
+{
+   Evas_Object *obj;
+   Evas_Object *lay;
+   Eina_List *subs;
+   Eina_List *parts_cursors;
+   Eina_Bool needs_size_calc:1;
+};
+
+struct _Subinfo
+{
+   const char *part;
+   Evas_Object *obj;
+   enum {
+     SWALLOW,
+     BOX_APPEND,
+     BOX_PREPEND,
+     BOX_INSERT_BEFORE,
+     BOX_INSERT_AT,
+     TABLE_PACK,
+     TEXT
+   } type;
+   union {
+      union {
+         const Evas_Object *reference;
+         unsigned int pos;
+      } box;
+      struct {
+         unsigned short col, row, colspan, rowspan;
+      } table;
+      struct {
+         const char *text;
+      } text;
+   } p;
+};
+
+struct _Part_Cursor
+{
+   Evas_Object *obj;
+   const char *part;
+   const char *cursor;
+   const char *style;
+   Eina_Bool engine_only:1;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _sizing_eval(Widget_Data *wd);
+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 _part_cursor_free(Part_Cursor *pc);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   Part_Cursor *pc;
+
+   if (!wd) return;
+   EINA_LIST_FREE(wd->subs, si)
+     {
+       eina_stringshare_del(si->part);
+        if (si->type == TEXT)
+          eina_stringshare_del(si->p.text.text);
+       free(si);
+     }
+   EINA_LIST_FREE(wd->parts_cursors, pc) _part_cursor_free(pc);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_scale_set(wd->lay, elm_widget_scale_get(obj) *
+                         _elm_config->scale);
+   _sizing_eval(wd);
+}
+
+static void
+_changed_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->needs_size_calc)
+     {
+       _sizing_eval(wd);
+       wd->needs_size_calc = 0;
+     }
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_emit(wd->lay, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_add(wd->lay, emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(wd->lay, emission, source, func_cb,
+                                        data);
+}
+
+
+static void *
+_elm_layout_list_data_get(const Eina_List *list)
+{
+   Subinfo *si = eina_list_data_get(list);
+   return si->obj;
+}
+
+static Eina_Bool
+_elm_layout_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *items;
+   void *(*list_data_get) (const Eina_List *list);
+
+   if ((!wd) || (!wd->subs))
+     return EINA_FALSE;
+
+   /* Focus chain (This block is diferent of elm_win cycle)*/
+   if ((items = elm_widget_focus_custom_chain_get(obj)))
+     list_data_get = eina_list_data_get;
+   else
+     {
+        items = wd->subs;
+        list_data_get = _elm_layout_list_data_get;
+
+        if (!items) return EINA_FALSE;
+     }
+
+   return elm_widget_focus_list_next_get(obj, items, list_data_get, dir,
+                                          next);
+}
+
+static void
+_sizing_eval(Widget_Data *wd)
+{
+   Evas_Coord minw = -1, minh = -1;
+   edje_object_size_min_calc(wd->lay, &minw, &minh);
+   evas_object_size_hint_min_set(wd->obj, minw, minh);
+   evas_object_size_hint_max_set(wd->obj, -1, -1);
+}
+
+static void
+_request_sizing_eval(Widget_Data *wd)
+{
+   if (wd->needs_size_calc) return;
+   wd->needs_size_calc = 1;
+   evas_object_smart_changed(wd->obj);
+}
+
+static void
+_part_cursor_free(Part_Cursor *pc)
+{
+   eina_stringshare_del(pc->part);
+   eina_stringshare_del(pc->style);
+   eina_stringshare_del(pc->cursor);
+   free(pc);
+}
+
+static void
+_part_cursor_part_apply(const Part_Cursor *pc)
+{
+   elm_object_cursor_set(pc->obj, pc->cursor);
+   elm_object_cursor_style_set(pc->obj, pc->style);
+   elm_object_cursor_engine_only_set(pc->obj, pc->engine_only);
+}
+
+static Part_Cursor *
+_parts_cursors_find(Widget_Data *wd, const char *part)
+{
+   const Eina_List *l;
+   Part_Cursor *pc;
+   EINA_LIST_FOREACH(wd->parts_cursors, l, pc)
+     {
+        if (!strcmp(pc->part, part))
+          return pc;
+     }
+   return NULL;
+}
+
+static void
+_parts_cursors_apply(Widget_Data *wd)
+{
+   const char *file, *group;
+   const Eina_List *l;
+   Part_Cursor *pc;
+
+   edje_object_file_get(wd->lay, &file, &group);
+
+   EINA_LIST_FOREACH(wd->parts_cursors, l, pc)
+     {
+        Evas_Object *obj = (Evas_Object *)edje_object_part_object_get
+          (wd->lay, pc->part);
+
+        if (!obj)
+          {
+             pc->obj = NULL;
+             WRN("no part '%s' in group '%s' of file '%s'. "
+                 "Cannot set cursor '%s'",
+                 pc->part, group, file, pc->cursor);
+             continue;
+          }
+        else if (evas_object_pass_events_get(obj))
+          {
+             pc->obj = NULL;
+             WRN("part '%s' in group '%s' of file '%s' has mouse_events: 0. "
+                 "Cannot set cursor '%s'",
+                 pc->part, group, file, pc->cursor);
+             continue;
+          }
+
+        pc->obj = obj;
+        _part_cursor_part_apply(pc);
+     }
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _request_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;
+   Eina_List *l;
+   Subinfo *si;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+       if (si->obj == sub)
+         {
+            evas_object_event_callback_del_full(sub,
+                                            EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints,
+                                            wd);
+            wd->subs = eina_list_remove_list(wd->subs, l);
+            eina_stringshare_del(si->part);
+            free(si);
+            break;
+         }
+     }
+}
+
+static void
+_signal_size_eval(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _request_sizing_eval(data);
+}
+
+static void
+_parts_text_fix(Widget_Data *wd)
+{
+   const Eina_List *l;
+   Subinfo *si;
+
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+        if (si->type == TEXT)
+          edje_object_part_text_set(wd->lay, si->part, si->p.text.text);
+     }
+}
+
+/**
+ * Add a new layout to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Layout
+ */
+EAPI Evas_Object *
+elm_layout_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   wd->obj = obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "layout");
+   elm_widget_type_set(obj, "layout");
+   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_changed_hook_set(obj, _changed_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+   elm_widget_focus_next_hook_set(obj, _elm_layout_focus_next_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+
+   wd->lay = edje_object_add(e);
+   elm_widget_resize_object_set(obj, wd->lay);
+   edje_object_signal_callback_add(wd->lay, "size,eval", "elm",
+                                   _signal_size_eval, wd);
+   
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _request_sizing_eval(wd);
+   return obj;
+}
+
+/**
+ * Set the file that will be used as layout
+ *
+ * @param obj The layout object
+ * @param file The path to file (edj) that will be used as layout
+ * @param group The group that the layout belongs in edje file
+ *
+ * @return (1 = success, 0 = error)
+ *
+ * @ingroup Layout
+ */
+EAPI Eina_Bool
+elm_layout_file_set(Evas_Object *obj, const char *file, const char *group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   Eina_Bool ret = edje_object_file_set(wd->lay, file, group);
+   if (ret)
+     {
+        _parts_text_fix(wd);
+        _request_sizing_eval(wd);
+        _parts_cursors_apply(wd);
+     }
+   else DBG("failed to set edje file '%s', group '%s': %s",
+            file, group,
+            edje_load_error_str(edje_object_load_error_get(wd->lay)));
+   return ret;
+}
+
+/**
+ * Set the edje group from the elementary theme that will be used as layout
+ *
+ * @param obj The layout object
+ * @param clas the clas of the group
+ * @param group the group
+ * @param style the style to used
+ *
+ * @return (1 = success, 0 = error)
+ *
+ * @ingroup Layout
+ */
+EAPI Eina_Bool
+elm_layout_theme_set(Evas_Object *obj, const char *clas, const char *group, const char *style)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   Eina_Bool ret = _elm_theme_object_set(obj, wd->lay, clas, group, style);
+   if (ret)
+     {
+        _parts_text_fix(wd);
+        _request_sizing_eval(wd);
+        _parts_cursors_apply(wd);
+     }
+   return ret;
+}
+
+/**
+ * Set the layout content
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_layout_content_unset() function.
+ *
+ * @param obj The layout object
+ * @param swallow The swallow group name in the edje file
+ * @param content The content will be filled in this layout object
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_content_set(Evas_Object *obj, const char *swallow, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   const Eina_List *l;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+       if ((si->type == SWALLOW) && (!strcmp(swallow, si->part)))
+         {
+            if (content == si->obj) return;
+            evas_object_del(si->obj);
+            break;
+         }
+     }
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+       evas_object_event_callback_add(content,
+                                       EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, wd);
+       if (!edje_object_part_swallow(wd->lay, swallow, content))
+          WRN("could not swallow %p into part '%s'", content, swallow);
+       si = ELM_NEW(Subinfo);
+        si->type = SWALLOW;
+       si->part = eina_stringshare_add(swallow);
+       si->obj = content;
+       wd->subs = eina_list_append(wd->subs, si);
+     }
+   _request_sizing_eval(wd);
+}
+
+/**
+ * Get the swallowed object in the given part
+ *
+ * @param obj The layout object
+ * @param swallow The SWALLOW part to get its content
+ *
+ * @return The swallowed object or NULL if none or an error occurred
+ *
+ * @ingroup Layout
+ */
+EAPI const Evas_Object *
+elm_layout_content_get(const Evas_Object *obj, const char *swallow)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *l;
+   Subinfo *si;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+        if ((si->type == SWALLOW) && !strcmp(swallow, si->part))
+          return si->obj;
+     }
+   return NULL;
+}
+
+/**
+ * Unset the layout content
+ *
+ * Unparent and return the content object which was set for this widget
+ *
+ * @param obj The layout object
+ * @param swallow The swallow group name in the edje file
+ * @return The content that was being used
+ *
+ * @ingroup Layout
+ */
+EAPI Evas_Object *
+elm_layout_content_unset(Evas_Object *obj, const char *swallow)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   const Eina_List *l;
+   if (!wd) return NULL;
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+       if ((si->type == SWALLOW) && (!strcmp(swallow, si->part)))
+         {
+            Evas_Object *content;
+            if (!si->obj) return NULL;
+            content = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */
+            elm_widget_sub_object_del(obj, content);
+            edje_object_part_unswallow(wd->lay, content);
+            return content;
+         }
+     }
+   return NULL;
+}
+
+/**
+ * Set the text of the given part
+ *
+ * @param obj The layout object
+ * @param part The TEXT part where to set the text
+ * @param text The text to set
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_text_set(Evas_Object *obj, const char *part, const char *text)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si = NULL;
+   Eina_List *l;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+        if ((si->type == TEXT) && (!strcmp(part, si->part)))
+          {
+             if (!text)
+               {
+                  eina_stringshare_del(si->part);
+                  eina_stringshare_del(si->p.text.text);
+                  free(si);
+                  edje_object_part_text_set(wd->lay, part, NULL);
+                  wd->subs = eina_list_remove_list(wd->subs, l);
+                  return;
+               }
+             else
+               break;
+          }
+        si = NULL;
+     }
+
+   if (!si)
+     {
+        si = ELM_NEW(Subinfo);
+        if (!si) return;
+        si->type = TEXT;
+        si->part = eina_stringshare_add(part);
+        wd->subs = eina_list_append(wd->subs, si);
+     }
+
+   eina_stringshare_replace(&si->p.text.text, text);
+   edje_object_part_text_set(wd->lay, part, text);
+   _request_sizing_eval(wd);
+}
+
+/**
+ * Get the text set in the given part
+ *
+ * @param obj The layout object
+ * @param part The TEXT part to retrieve the text off
+ *
+ * @return The text set in @p part
+ *
+ * @ingroup Layout
+ */
+EAPI const char *
+elm_layout_text_get(const Evas_Object *obj, const char *part)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return edje_object_part_text_get(wd->lay, part);
+}
+
+/**
+ * Append child to layout box part.
+ *
+ * Once the object is appended, its lifetime will be bound to the
+ * layout, whenever the layout dies the child will be deleted
+ * automatically. One should use elm_layout_box_remove() to make this
+ * layout forget about the object.
+ *
+ * @param obj the layout object
+ * @param part the box part to append.
+ * @param child the child object to append to box.
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_box_append(Evas_Object *obj, const char *part, Evas_Object *child)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   if (!wd) return;
+
+   if (!edje_object_part_box_append(wd->lay, part, child))
+     WRN("child %p could not be appended to box part '%s'", child, part);
+   elm_widget_sub_object_add(obj, child);
+   evas_object_event_callback_add
+     (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
+
+   si = ELM_NEW(Subinfo);
+   si->type = BOX_APPEND;
+   si->part = eina_stringshare_add(part);
+   si->obj = child;
+   wd->subs = eina_list_append(wd->subs, si);
+   _request_sizing_eval(wd);
+}
+
+/**
+ * Prepend child to layout box part.
+ *
+ * Once the object is prepended, its lifetime will be bound to the
+ * layout, whenever the layout dies the child will be deleted
+ * automatically. One should use elm_layout_box_remove() to make this
+ * layout forget about the object.
+ *
+ * @param obj the layout object
+ * @param part the box part to prepend.
+ * @param child the child object to prepend to box.
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_box_prepend(Evas_Object *obj, const char *part, Evas_Object *child)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   if (!wd) return;
+
+   if (!edje_object_part_box_prepend(wd->lay, part, child))
+     WRN("child %p could not be prepended to box part '%s'", child, part);
+   elm_widget_sub_object_add(obj, child);
+   evas_object_event_callback_add
+     (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
+
+   si = ELM_NEW(Subinfo);
+   si->type = BOX_PREPEND;
+   si->part = eina_stringshare_add(part);
+   si->obj = child;
+   wd->subs = eina_list_prepend(wd->subs, si);
+   _request_sizing_eval(wd);
+}
+
+static void
+_box_reference_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Subinfo *si = data;
+   si->p.box.reference = NULL;
+}
+
+/**
+ * Insert child to layout box part before a reference object.
+ *
+ * Once the object is inserted, its lifetime will be bound to the
+ * layout, whenever the layout dies the child will be deleted
+ * automatically. One should use elm_layout_box_remove() to make this
+ * layout forget about the object.
+ *
+ * @param obj the layout object
+ * @param part the box part to insert.
+ * @param child the child object to insert into box.
+ * @param reference another reference object to insert before in box.
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_box_insert_before(Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   if (!wd) return;
+
+   if (!edje_object_part_box_insert_before(wd->lay, part, child, reference))
+     WRN("child %p could not be inserted before %p inf box part '%s'",
+         child, reference, part);
+
+   si = ELM_NEW(Subinfo);
+   si->type = BOX_INSERT_BEFORE;
+   si->part = eina_stringshare_add(part);
+   si->obj = child;
+   si->p.box.reference = reference;
+
+   elm_widget_sub_object_add(obj, child);
+   evas_object_event_callback_add
+     (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
+   evas_object_event_callback_add
+     ((Evas_Object *)reference, EVAS_CALLBACK_DEL, _box_reference_del, si);
+
+   wd->subs = eina_list_append(wd->subs, si);
+   _request_sizing_eval(wd);
+}
+
+/**
+ * Insert child to layout box part at a given position.
+ *
+ * Once the object is inserted, its lifetime will be bound to the
+ * layout, whenever the layout dies the child will be deleted
+ * automatically. One should use elm_layout_box_remove() to make this
+ * layout forget about the object.
+ *
+ * @param obj the layout object
+ * @param part the box part to insert.
+ * @param child the child object to insert into box.
+ * @param pos the numeric position >=0 to insert the child.
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   if (!wd) return;
+
+   if (!edje_object_part_box_insert_at(wd->lay, part, child, pos))
+     WRN("child %p could not be inserted at %u to box part '%s'",
+         child, pos, part);
+
+   elm_widget_sub_object_add(obj, child);
+   evas_object_event_callback_add
+     (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
+
+   si = ELM_NEW(Subinfo);
+   si->type = BOX_INSERT_AT;
+   si->part = eina_stringshare_add(part);
+   si->obj = child;
+   si->p.box.pos = pos;
+   wd->subs = eina_list_append(wd->subs, si);
+   _request_sizing_eval(wd);
+}
+
+static Evas_Object *
+_sub_box_remove(Widget_Data *wd, Subinfo *si)
+{
+   Evas_Object *child;
+
+   if (si->type == BOX_INSERT_BEFORE)
+     evas_object_event_callback_del_full
+       ((Evas_Object *)si->p.box.reference,
+        EVAS_CALLBACK_DEL, _box_reference_del, si);
+
+   child = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */
+   edje_object_part_box_remove(wd->lay, si->part, child);
+   elm_widget_sub_object_del(wd->obj, child);
+   return child;
+}
+
+static Evas_Object *
+_sub_table_remove(Widget_Data *wd, Subinfo *si)
+{
+   Evas_Object *child;
+
+   child = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */
+   edje_object_part_table_unpack(wd->lay, si->part, child);
+   elm_widget_sub_object_del(wd->obj, child);
+   return child;
+}
+
+static Eina_Bool
+_sub_box_is(const Subinfo *si)
+{
+   switch (si->type)
+     {
+      case BOX_APPEND:
+      case BOX_PREPEND:
+      case BOX_INSERT_BEFORE:
+      case BOX_INSERT_AT:
+         return EINA_TRUE;
+      default:
+         return EINA_FALSE;
+     }
+}
+
+/**
+ * Remove a child of the given part box.
+ *
+ * The object will be removed from the box part and its lifetime will
+ * not be handled by the layout anymore. This is equivalent to
+ * elm_layout_content_unset() for box.
+ *
+ * @param obj The layout object
+ * @param part The box part name to remove child.
+ * @param child The object to remove from box.
+ * @return The object that was being used, or NULL if not found.
+ *
+ * @ingroup Layout
+ */
+EAPI Evas_Object *
+elm_layout_box_remove(Evas_Object *obj, const char *part, Evas_Object *child)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *l;
+   Subinfo *si;
+
+   if (!wd) return NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL);
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+        if (!_sub_box_is(si)) continue;
+        if ((si->obj == child) && (!strcmp(si->part, part)))
+          return _sub_box_remove(wd, si);
+     }
+   return NULL;
+}
+
+/**
+ * Remove all child of the given part box.
+ *
+ * The objects will be removed from the box part and their lifetime will
+ * not be handled by the layout anymore. This is equivalent to
+ * elm_layout_content_unset() for all box children.
+ *
+ * @param obj The layout object
+ * @param part The box part name to remove child.
+ * @param clear If EINA_TRUE, then all objects will be deleted as
+ *        well, otherwise they will just be removed and will be
+ *        dangling on the canvas.
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool clear)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   Eina_List *lst;
+
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(part);
+
+   lst = eina_list_clone(wd->subs);
+   EINA_LIST_FREE(lst, si)
+     {
+        if (!_sub_box_is(si)) continue;
+        if (!strcmp(si->part, part))
+          {
+             Evas_Object *child = _sub_box_remove(wd, si);
+             if ((clear) && (child)) evas_object_del(child);
+          }
+     }
+   /* eventually something may not be added with layout, del them as well */
+   edje_object_part_box_remove_all(wd->lay, part, clear);
+}
+
+/**
+ * Insert child to layout table part.
+ *
+ * Once the object is inserted, its lifetime will be bound to the
+ * layout, whenever the layout dies the child will be deleted
+ * automatically. One should use elm_layout_box_remove() to make this
+ * layout forget about the object.
+ *
+ * @param obj the layout object
+ * @param part the box part to pack child.
+ * @param child the child object to pack into table.
+ * @param reference another reference object to insert before in box.
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_table_pack(Evas_Object *obj, const char *part, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   if (!wd) return;
+
+   if (!edje_object_part_table_pack
+       (wd->lay, part, child, col, row, colspan, rowspan))
+     WRN("child %p could not be packed into box part '%s' col=%uh, row=%hu, "
+         "colspan=%hu, rowspan=%hu", child, part, col, row, colspan, rowspan);
+
+   elm_widget_sub_object_add(obj, child);
+   evas_object_event_callback_add
+     (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
+
+   si = ELM_NEW(Subinfo);
+   si->type = TABLE_PACK;
+   si->part = eina_stringshare_add(part);
+   si->obj = child;
+   si->p.table.col = col;
+   si->p.table.row = row;
+   si->p.table.colspan = colspan;
+   si->p.table.rowspan = rowspan;
+   wd->subs = eina_list_append(wd->subs, si);
+   _request_sizing_eval(wd);
+}
+
+/**
+ * Unpack (remove) a child of the given part table.
+ *
+ * The object will be unpacked from the table part and its lifetime
+ * will not be handled by the layout anymore. This is equivalent to
+ * elm_layout_content_unset() for table.
+ *
+ * @param obj The layout object
+ * @param part The table part name to remove child.
+ * @param child The object to remove from table.
+ * @return The object that was being used, or NULL if not found.
+ *
+ * @ingroup Layout
+ */
+EAPI Evas_Object *
+elm_layout_table_unpack(Evas_Object *obj, const char *part, Evas_Object *child)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *l;
+   Subinfo *si;
+
+   if (!wd) return NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL);
+   EINA_LIST_FOREACH(wd->subs, l, si)
+     {
+        if (si->type != TABLE_PACK) continue;
+        if ((si->obj == child) && (!strcmp(si->part, part)))
+          return _sub_table_remove(wd, si);
+     }
+   return NULL;
+}
+
+/**
+ * Remove all child of the given part table.
+ *
+ * The objects will be removed from the table part and their lifetime will
+ * not be handled by the layout anymore. This is equivalent to
+ * elm_layout_content_unset() for all table children.
+ *
+ * @param obj The layout object
+ * @param part The table part name to remove child.
+ * @param clear If EINA_TRUE, then all objects will be deleted as
+ *        well, otherwise they will just be removed and will be
+ *        dangling on the canvas.
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_table_clear(Evas_Object *obj, const char *part, Eina_Bool clear)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Subinfo *si;
+   Eina_List *lst;
+
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(part);
+
+   lst = eina_list_clone(wd->subs);
+   EINA_LIST_FREE(lst, si)
+     {
+        if (si->type != TABLE_PACK) continue;
+        if (!strcmp(si->part, part))
+          {
+             Evas_Object *child = _sub_table_remove(wd, si);
+             if ((clear) && (child)) evas_object_del(child);
+          }
+     }
+   /* eventually something may not be added with layout, del them as well */
+   edje_object_part_table_clear(wd->lay, part, clear);
+}
+
+/**
+ * Get the edje layout
+ *
+ * @param obj The layout object
+ * 
+ * This returns the edje object. It is not expected to be used to then swallow
+ * objects via edje_object_part_swallow() for example. Use 
+ * elm_layout_content_set() instead so child object handling and sizing is
+ * done properly. This is more intended for setting text, emitting signals,
+ * hooking to signal callbacks etc.
+ *
+ * @return A Evas_Object with the edje layout settings loaded
+ * with function elm_layout_file_set
+ *
+ * @ingroup Layout
+ */
+EAPI Evas_Object *
+elm_layout_edje_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->lay;
+}
+
+/**
+ * Get the edje data of the given layout
+ *
+ * @param obj The layout object
+ * @param key The data key
+ *
+ * @return The edje data string
+ *
+ * This function fetches data specified at the object level.
+ * This function return NULL if data is not found.
+ *
+ * In EDC this comes from a data block within the group block that @a
+ * obj was loaded from. E.g.
+ *
+ * @code
+ * collections {
+ *   group {
+ *     name: "a_group";
+ *     data {
+ *      item: "key1" "value1";
+ *      item: "key2" "value2";
+ *     }
+ *   }
+ * }
+ * @endcode
+ *
+ * @ingroup Layout
+ */
+EAPI const char *
+elm_layout_data_get(const Evas_Object *obj, const char *key)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return edje_object_data_get(wd->lay, key);
+}
+
+/**
+ * Eval sizing
+ *
+ * Manually forms a sizing re-evaluation when contents changed state so that
+ * minimum size might have changed and needs re-evaluation. Also note that
+ * a standard signal of "size,eval" "elm" emitted by the edje object will
+ * cause this to happen too
+ *
+ * @param obj The layout object
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_sizing_eval(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(wd);
+   _request_sizing_eval(wd);
+}
+
+/**
+ * Sets a specific cursor for an edje part.
+ *
+ * @param obj The layout object.
+ * @param part_name a part from loaded edje group.
+ * @param cursor cursor name to use, see Elementary_Cursor.h
+ *
+ * @return EINA_TRUE on success or EINA_FALSE on failure, that may be
+ *         part not exists or it has "mouse_events: 0".
+ *
+ * @ingroup Layout
+ */
+EAPI Eina_Bool
+elm_layout_part_cursor_set(Evas_Object *obj, const char *part_name, const char *cursor)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
+   Evas_Object *part_obj;
+   Part_Cursor *pc;
+
+   part_obj = (Evas_Object *)edje_object_part_object_get(wd->lay, part_name);
+   if (!part_obj)
+     {
+        const char *group, *file;
+        edje_object_file_get(wd->lay, &file, &group);
+        WRN("no part '%s' in group '%s' of file '%s'. Cannot set cursor '%s'",
+            part_name, group, file, cursor);
+        return EINA_FALSE;
+     }
+   if (evas_object_pass_events_get(part_obj))
+     {
+        const char *group, *file;
+        edje_object_file_get(wd->lay, &file, &group);
+        WRN("part '%s' in group '%s' of file '%s' has mouse_events: 0. "
+            "Cannot set cursor '%s'",
+            part_name, group, file, cursor);
+        return EINA_FALSE;
+     }
+
+   pc = _parts_cursors_find(wd, part_name);
+   if (pc) eina_stringshare_replace(&pc->cursor, cursor);
+   else
+     {
+        pc = calloc(1, sizeof(*pc));
+        pc->part = eina_stringshare_add(part_name);
+        pc->cursor = eina_stringshare_add(cursor);
+     }
+
+   pc->obj = part_obj;
+   elm_object_sub_cursor_set(part_obj, obj, pc->cursor);
+   return EINA_TRUE;
+}
+
+/**
+ * Get the cursor to be shown when mouse is over an edje part
+ *
+ * @param obj The layout object.
+ * @param part_name a part from loaded edje group.
+ * @return the cursor name.
+ *
+ * @ingroup Layout
+ */
+EAPI const char *
+elm_layout_part_cursor_get(const Evas_Object *obj, const char *part_name)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
+   Part_Cursor *pc = _parts_cursors_find(wd, part_name);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL);
+   return elm_object_cursor_get(pc->obj);
+}
+
+/**
+ * Unsets a cursor previously set with elm_layout_part_cursor_set().
+ *
+ * @param obj The layout object.
+ * @param part_name a part from loaded edje group, that had a cursor set
+ *        with elm_layout_part_cursor_set().
+ *
+ * @ingroup Layout
+ */
+EAPI void
+elm_layout_part_cursor_unset(Evas_Object *obj, const char *part_name)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   EINA_SAFETY_ON_NULL_RETURN(part_name);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(wd);
+   Eina_List *l;
+   Part_Cursor *pc;
+
+   EINA_LIST_FOREACH(wd->parts_cursors, l, pc)
+     {
+        if (!strcmp(part_name, pc->part))
+          {
+             if (pc->obj) elm_object_cursor_unset(pc->obj);
+             _part_cursor_free(pc);
+             wd->parts_cursors = eina_list_remove_list(wd->parts_cursors, l);
+             return;
+          }
+     }
+}
+
+/**
+ * Sets a specific cursor style for an edje part.
+ *
+ * @param obj The layout object.
+ * @param part_name a part from loaded edje group.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @return EINA_TRUE on success or EINA_FALSE on failure, that may be
+ *         part not exists or it did not had a cursor set.
+ *
+ * @ingroup Layout
+ */
+EAPI Eina_Bool
+elm_layout_part_cursor_style_set(Evas_Object *obj, const char *part_name, const char *style)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
+   Part_Cursor *pc = _parts_cursors_find(wd, part_name);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
+
+   eina_stringshare_replace(&pc->style, style);
+   elm_object_cursor_style_set(pc->obj, pc->style);
+   return EINA_TRUE;
+}
+
+/**
+ * Gets a specific cursor style for an edje part.
+ *
+ * @param obj The layout object.
+ * @param part_name a part from loaded edje group.
+ *
+ * @return the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup Layout
+ */
+EAPI const char *
+elm_layout_part_cursor_style_get(const Evas_Object *obj, const char *part_name)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
+   Part_Cursor *pc = _parts_cursors_find(wd, part_name);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL);
+   return elm_object_cursor_style_get(pc->obj);
+}
+
+/**
+ * Sets if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a
+ * cursor with elm_layout_part_cursor_set(). By default it will only
+ * look for cursors provided by the engine.
+ *
+ * @param obj The layout object.
+ * @param part_name a part from loaded edje group.
+ * @param engine_only if cursors should be just provided by the engine
+ *        or should also search on widget's theme as well
+ *
+ * @return EINA_TRUE on success or EINA_FALSE on failure, that may be
+ *         part not exists or it did not had a cursor set.
+ *
+ * @ingroup Layout
+ */
+EAPI Eina_Bool
+elm_layout_part_cursor_engine_only_set(Evas_Object *obj, const char *part_name, Eina_Bool engine_only)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
+   Part_Cursor *pc = _parts_cursors_find(wd, part_name);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
+
+   pc->engine_only = !!engine_only;
+   elm_object_cursor_engine_only_set(pc->obj, pc->engine_only);
+   return EINA_TRUE;
+}
+
+/**
+ * Gets a specific cursor engine_only for an edje part.
+ *
+ * @param obj The layout object.
+ * @param part_name a part from loaded edje group.
+ *
+ * @return whenever the cursor is just provided by engine or also from theme.
+ *
+ * @ingroup Layout
+ */
+EAPI Eina_Bool
+elm_layout_part_cursor_engine_only_get(const Evas_Object *obj, const char *part_name)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
+   Part_Cursor *pc = _parts_cursors_find(wd, part_name);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
+   return elm_object_cursor_engine_only_get(pc->obj);
+}
+
+
+
diff --git a/src/lib/elm_list.c b/src/lib/elm_list.c
new file mode 100644 (file)
index 0000000..73906bc
--- /dev/null
@@ -0,0 +1,2497 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define SWIPE_MOVES 12
+
+/**
+ * @defgroup List List
+ *
+ * A list is a very simple type of list widget.  For more robust
+ * lists, @ref Genlist should probably be used.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *scr, *box, *self;
+   Eina_List *items, *selected, *to_delete;
+   Elm_List_Item *last_selected_item;
+   Elm_List_Mode mode;
+   Elm_List_Mode h_mode;
+   Evas_Coord minw[2], minh[2];
+   Eina_Bool scr_minw : 1;
+   Eina_Bool scr_minh : 1;
+   int walking;
+   int movements;
+   struct
+   {
+      Evas_Coord x, y;
+   } history[SWIPE_MOVES];
+   Eina_Bool swipe : 1;
+   Eina_Bool fix_pending : 1;
+   Eina_Bool on_hold : 1;
+   Eina_Bool multi : 1;
+   Eina_Bool always_select : 1;
+   Eina_Bool longpressed : 1;
+   Eina_Bool wasselected : 1;
+};
+
+struct _Elm_List_Item
+{
+   Elm_Widget_Item base;
+   Widget_Data *wd;
+   Eina_List *node;
+   const char *label;
+   Evas_Object *icon, *end;
+   Evas_Smart_Cb func;
+   Ecore_Timer *long_timer;
+   Ecore_Timer *swipe_timer;
+   Eina_Bool deleted : 1;
+   Eina_Bool disabled : 1;
+   Eina_Bool even : 1;
+   Eina_Bool is_even : 1;
+   Eina_Bool is_separator : 1;
+   Eina_Bool fixed : 1;
+   Eina_Bool selected : 1;
+   Eina_Bool hilighted : 1;
+   Eina_Bool dummy_icon : 1;
+   Eina_Bool dummy_end : 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 _disable_hook(Evas_Object *obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source);
+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 _fix_items(Evas_Object *obj);
+static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+static void _scroll_edge_left(void *data, Evas_Object *scr, void *event_info);
+static void _scroll_edge_right(void *data, Evas_Object *scr, void *event_info);
+static void _scroll_edge_top(void *data, Evas_Object *scr, void *event_info);
+static void _scroll_edge_bottom(void *data, Evas_Object *scr, void *event_info);
+static Eina_Bool _item_multi_select_up(Widget_Data *wd);
+static Eina_Bool _item_multi_select_down(Widget_Data *wd);
+static Eina_Bool _item_single_select_up(Widget_Data *wd);
+static Eina_Bool _item_single_select_down(Widget_Data *wd);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+static Eina_Bool _deselect_all_items(Widget_Data *wd);
+
+#define ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ...)                    \
+  ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, __VA_ARGS__);             \
+  if (it->deleted)                                                      \
+    {                                                                  \
+       ERR("ERROR: "#it" has been DELETED.\n");                         \
+       return __VA_ARGS__;                                             \
+    }
+
+static inline void
+_elm_list_item_free(Elm_List_Item *it)
+{
+   evas_object_event_callback_del_full
+     (it->base.view, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
+   evas_object_event_callback_del_full
+     (it->base.view, EVAS_CALLBACK_MOUSE_UP, _mouse_up, it);
+   evas_object_event_callback_del_full
+     (it->base.view, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, it);
+
+   if (it->icon)
+     evas_object_event_callback_del_full
+       (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+        _changed_size_hints, it->base.widget);
+
+   if (it->end)
+     evas_object_event_callback_del_full
+       (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+        _changed_size_hints, it->base.widget);
+
+   eina_stringshare_del(it->label);
+
+   if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
+   if (it->long_timer) ecore_timer_del(it->long_timer);
+   if (it->icon) evas_object_del(it->icon);
+   if (it->end) evas_object_del(it->end);
+
+   elm_widget_item_del(it);
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (!wd->items) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   Elm_List_Item *it = NULL;
+   Evas_Coord x = 0;
+   Evas_Coord y = 0;
+   Evas_Coord step_x = 0;
+   Evas_Coord step_y = 0;
+   Evas_Coord v_w = 0;
+   Evas_Coord v_h = 0;
+   Evas_Coord page_x = 0;
+   Evas_Coord page_y = 0;
+
+   elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
+   elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
+   elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
+
+   /* TODO: fix logic for horizontal mode */
+   if ((!strcmp(ev->keyname, "Left")) ||
+       (!strcmp(ev->keyname, "KP_Left")))
+     {
+        if ((wd->h_mode) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_up(wd)))
+             || (_item_single_select_up(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          x -= step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Right")) ||
+            (!strcmp(ev->keyname, "KP_Right")))
+     {
+        if ((wd->h_mode) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_down(wd)))
+             || (_item_single_select_down(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          x += step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Up"))  ||
+            (!strcmp(ev->keyname, "KP_Up")))
+     {
+        if ((!wd->h_mode) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_up(wd)))
+             || (_item_single_select_up(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          y -= step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Down")) ||
+            (!strcmp(ev->keyname, "KP_Down")))
+     {
+        if ((!wd->h_mode) &&
+            (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
+              (_item_multi_select_down(wd)))
+             || (_item_single_select_down(wd))))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else
+          y += step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Home")) ||
+            (!strcmp(ev->keyname, "KP_Home")))
+     {
+        it = eina_list_data_get(wd->items);
+        elm_list_item_bring_in(it);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "End")) ||
+            (!strcmp(ev->keyname, "KP_End")))
+     {
+        it = eina_list_data_get(eina_list_last(wd->items));
+        elm_list_item_bring_in(it);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "Prior")) ||
+            (!strcmp(ev->keyname, "KP_Prior")))
+     {
+        if (wd->h_mode)
+          {
+             if (page_x < 0)
+               x -= -(page_x * v_w) / 100;
+             else
+               x -= page_x;
+          }
+        else
+          {
+             if (page_y < 0)
+               y -= -(page_y * v_h) / 100;
+             else
+               y -= page_y;
+          }
+     }
+   else if ((!strcmp(ev->keyname, "Next")) ||
+            (!strcmp(ev->keyname, "KP_Next")))
+     {
+        if (wd->h_mode)
+          {
+             if (page_x < 0)
+               x += -(page_x * v_w) / 100;
+             else
+               x += page_x;
+          }
+        else
+          {
+             if (page_y < 0)
+               y += -(page_y * v_h) / 100;
+             else
+               y += page_y;
+          }
+     }
+   else if (!strcmp(ev->keyname, "Escape"))
+     {
+       if (!_deselect_all_items(wd)) return EINA_FALSE;
+       ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+       return EINA_TRUE;
+     }
+   else return EINA_FALSE;
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   elm_smart_scroller_child_pos_set(wd->scr, x, y);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_deselect_all_items(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   while(wd->selected)
+     elm_list_item_selected_set(wd->selected->data, EINA_FALSE);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_up(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   if (!wd->multi) return EINA_FALSE;
+
+   Elm_List_Item *prev = elm_list_item_prev(wd->last_selected_item);
+   if (!prev) return EINA_TRUE;
+
+   if (elm_list_item_selected_get(prev))
+     {
+        elm_list_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = prev;
+        elm_list_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_list_item_selected_set(prev, EINA_TRUE);
+        elm_list_item_show(prev);
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_multi_select_down(Widget_Data *wd)
+{
+   if (!wd->selected) return EINA_FALSE;
+   if (!wd->multi) return EINA_FALSE;
+
+   Elm_List_Item *next = elm_list_item_next(wd->last_selected_item);
+   if (!next) return EINA_TRUE;
+
+   if (elm_list_item_selected_get(next))
+     {
+        elm_list_item_selected_set(wd->last_selected_item, EINA_FALSE);
+        wd->last_selected_item = next;
+        elm_list_item_show(wd->last_selected_item);
+     }
+   else
+     {
+        elm_list_item_selected_set(next, EINA_TRUE);
+        elm_list_item_show(next);
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_up(Widget_Data *wd)
+{
+   Elm_List_Item *prev;
+
+   if (!wd->selected) prev = eina_list_data_get(eina_list_last(wd->items));
+   else prev = elm_list_item_prev(wd->last_selected_item);
+
+   if (!prev) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_list_item_selected_set(prev, EINA_TRUE);
+   elm_list_item_show(prev);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_item_single_select_down(Widget_Data *wd)
+{
+   Elm_List_Item *next;
+
+   if (!wd->selected) next = eina_list_data_get(wd->items);
+   else next = elm_list_item_next(wd->last_selected_item);
+
+   if (!next) return EINA_FALSE;
+
+   _deselect_all_items(wd);
+
+   elm_list_item_selected_set(next, EINA_TRUE);
+   elm_list_item_show(next);
+   return EINA_TRUE;
+}
+
+static void
+_elm_list_process_deletions(Widget_Data *wd)
+{
+   Elm_List_Item *it;
+
+   wd->walking++; // avoid nested deletion and also _sub_del() fix_items
+
+   EINA_LIST_FREE(wd->to_delete, it)
+     {
+        elm_widget_item_pre_notify_del(it);
+
+        wd->items = eina_list_remove_list(wd->items, it->node);
+        _elm_list_item_free(it);
+     }
+
+   wd->walking--;
+}
+
+static inline void
+_elm_list_walk(Widget_Data *wd)
+{
+   if (wd->walking < 0)
+     {
+       ERR("ERROR: walking was negative. fixed!\n");
+       wd->walking = 0;
+     }
+   wd->walking++;
+}
+
+static inline void
+_elm_list_unwalk(Widget_Data *wd)
+{
+   wd->walking--;
+   if (wd->walking < 0)
+     {
+       ERR("ERROR: walking became negative. fixed!\n");
+       wd->walking = 0;
+     }
+
+   if (wd->walking)
+     return;
+
+   if (wd->to_delete)
+     _elm_list_process_deletions(wd);
+
+   if (wd->fix_pending)
+     {
+        wd->fix_pending = EINA_FALSE;
+        _fix_items(wd->self);
+        _sizing_eval(wd->self);
+     }
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_List_Item *it;
+   Eina_List *n;
+
+   if (!wd) return;
+   if (wd->walking)
+     ERR("ERROR: list deleted while walking.\n");
+
+   _elm_list_walk(wd);
+   EINA_LIST_FOREACH(wd->items, n, it) elm_widget_item_pre_notify_del(it);
+   _elm_list_unwalk(wd);
+   if (wd->to_delete)
+     ERR("ERROR: leaking nodes!\n");
+
+   EINA_LIST_FREE(wd->items, it) _elm_list_item_free(it);
+   eina_list_free(wd->selected);
+   free(wd);
+}
+
+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);
+   elm_smart_scroller_child_region_set(wd->scr, x, y, w, h);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (elm_widget_disabled_get(obj))
+     {
+        _signal_emit_hook(obj, "elm,state,disabled", "elm");
+        elm_widget_scroll_freeze_push(obj);
+        elm_widget_scroll_hold_push(obj);
+        /* FIXME: if we get to have a way to only un-hilight items
+         * in the future, keeping them selected... */
+        _deselect_all_items(wd);
+     }
+   else
+     {
+        _signal_emit_hook(obj, "elm,state,enabled", "elm");
+        elm_widget_scroll_freeze_pop(obj);
+        elm_widget_scroll_hold_pop(obj);
+     }
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   Evas_Coord  vw, vh, minw, minh, maxw, maxh, w, h, vmw, vmh;
+   double xw, yw;
+
+   evas_object_size_hint_min_get(wd->box, &minw, &minh);
+   evas_object_size_hint_max_get(wd->box, &maxw, &maxh);
+   evas_object_size_hint_weight_get(wd->box, &xw, &yw);
+   if (!wd->scr) return;
+   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 (yw > 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->box, vw, vh);
+   w = -1;
+   h = -1;
+   edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
+                             &vmw, &vmh);
+   if (wd->scr_minw) w = vmw + minw;
+   if (wd->scr_minh) h = vmh + minh;
+
+   evas_object_size_hint_max_get(obj, &maxw, &maxh);
+   if ((maxw > 0) && (w > maxw))
+     w = maxw;
+   if ((maxh > 0) && (h > maxh))
+     h = maxh;
+
+   evas_object_size_hint_min_set(obj, w, h);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                           emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
+                                   emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(
+                              elm_smart_scroller_edje_object_get(wd->scr),
+                              emission, source, func_cb, data);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_List_Item *it;
+   Eina_List *n;
+
+   if (!wd) return;
+   if (wd->scr)
+     {
+        Evas_Object *edj;
+        const char *str;
+
+        elm_smart_scroller_object_theme_set(obj, wd->scr, "list", "base",
+                                            elm_widget_style_get(obj));
+//        edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
+        edj = elm_smart_scroller_edje_object_get(wd->scr);
+        str = edje_object_data_get(edj, "focus_highlight");
+        if ((str) && (!strcmp(str, "on")))
+          elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
+        else
+          elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
+        elm_object_style_set(wd->scr, elm_widget_style_get(obj));
+     }
+   EINA_LIST_FOREACH(wd->items, n, it)
+     {
+        edje_object_scale_set(it->base.view, elm_widget_scale_get(obj) * _elm_config->scale);
+        it->fixed = 0;
+     }
+   _fix_items(obj);
+   _sizing_eval(obj);
+}
+
+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))
+     {
+        edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
+        evas_object_focus_set(wd->self, EINA_TRUE);
+
+        if ((wd->selected) && (!wd->last_selected_item))
+          wd->last_selected_item = eina_list_data_get(wd->selected);
+     }
+   else
+     {
+        edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
+        evas_object_focus_set(wd->self, EINA_FALSE);
+     }
+}
+
+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;
+   _fix_items(data);
+   _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;
+   const Eina_List *l;
+   Elm_List_Item *it;
+
+   if (!wd) return;
+   if (!sub) abort();
+   if (sub == wd->scr)
+     wd->scr = NULL;
+   else
+     {
+        EINA_LIST_FOREACH(wd->items, l, it)
+          {
+             if ((sub == it->icon) || (sub == it->end))
+               {
+                  if (it->icon == sub) it->icon = NULL;
+                  if (it->end == sub) it->end = NULL;
+                  evas_object_event_callback_del_full
+                    (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints,
+                     obj);
+                  if (!wd->walking)
+                    {
+                       _fix_items(obj);
+                       _sizing_eval(obj);
+                    }
+                  else
+                    wd->fix_pending = EINA_TRUE;
+                  break;
+               }
+          }
+     }
+}
+
+static void
+_item_hilight(Elm_List_Item *it)
+{
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   const char *selectraise;
+
+   if (!wd) return;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (it->hilighted) return;
+   _elm_list_walk(wd);
+
+   edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
+   selectraise = edje_object_data_get(it->base.view, "selectraise");
+   if ((selectraise) && (!strcmp(selectraise, "on")))
+     evas_object_raise(it->base.view);
+   it->hilighted = EINA_TRUE;
+
+   _elm_list_unwalk(wd);
+}
+
+static void
+_item_select(Elm_List_Item *it)
+{
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+
+   if (!wd) return;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (it->selected)
+     {
+        if (wd->always_select) goto call;
+        return;
+     }
+   it->selected = EINA_TRUE;
+   wd->selected = eina_list_append(wd->selected, it);
+   call:
+   _elm_list_walk(wd);
+
+   if (it->func) it->func((void *)it->base.data, it->base.widget, it);
+   evas_object_smart_callback_call(it->base.widget, "selected", it);
+
+   _elm_list_unwalk(wd);
+   it->wd->last_selected_item = it;
+}
+
+static void
+_item_unselect(Elm_List_Item *it)
+{
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   const char *stacking, *selectraise;
+
+   if (!wd) return;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (!it->hilighted) return;
+   _elm_list_walk(wd);
+
+   edje_object_signal_emit(it->base.view, "elm,state,unselected", "elm");
+   stacking = edje_object_data_get(it->base.view, "stacking");
+   selectraise = edje_object_data_get(it->base.view, "selectraise");
+   if ((selectraise) && (!strcmp(selectraise, "on")))
+     {
+        if ((stacking) && (!strcmp(stacking, "below")))
+           evas_object_lower(it->base.view);
+     }
+   it->hilighted = EINA_FALSE;
+   if (it->selected)
+     {
+        it->selected = EINA_FALSE;
+        wd->selected = eina_list_remove(wd->selected, it);
+        evas_object_smart_callback_call(it->base.widget, "unselected", it);
+     }
+
+   _elm_list_unwalk(wd);
+}
+
+static Eina_Bool
+_swipe_cancel(void *data)
+{
+   Elm_List_Item *it = data;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
+   wd->swipe = EINA_FALSE;
+   wd->movements = 0;
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_List_Item *it = data;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   Evas_Event_Mouse_Move *ev = event_info;
+
+   if (!wd) return;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     {
+        if (!wd->on_hold)
+          {
+             wd->on_hold = EINA_TRUE;
+             if (it->long_timer)
+               {
+                  ecore_timer_del(it->long_timer);
+                  it->long_timer = NULL;
+               }
+             if (!wd->wasselected)
+               _item_unselect(it);
+          }
+        if (wd->movements == SWIPE_MOVES) wd->swipe = EINA_TRUE;
+        else
+          {
+             wd->history[wd->movements].x = ev->cur.canvas.x;
+             wd->history[wd->movements].y = ev->cur.canvas.y;
+             if (abs((wd->history[wd->movements].x - wd->history[0].x)) > 40)
+                wd->swipe = EINA_TRUE;
+             else
+                wd->movements++;
+          }
+     }
+}
+
+static void
+_scroll_edge_left(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,left", NULL);
+}
+
+static void
+_scroll_edge_right(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,right", NULL);
+}
+
+static void
+_scroll_edge_top(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,top", NULL);
+}
+
+static void
+_scroll_edge_bottom(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   evas_object_smart_callback_call(obj, "scroll,edge,bottom", NULL);
+}
+
+static Eina_Bool
+_long_press(void *data)
+{
+   Elm_List_Item *it = data;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+
+   if (!wd)
+     goto end;
+
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
+
+   it->long_timer = NULL;
+
+   if (it->disabled)
+     goto end;
+
+   wd->longpressed = EINA_TRUE;
+   evas_object_smart_callback_call(it->base.widget, "longpressed", it);
+
+ end:
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_swipe(Elm_List_Item *it)
+{
+   int i, sum = 0;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (!wd) return;
+   wd->swipe = EINA_FALSE;
+   for (i = 0; i < wd->movements; i++)
+     {
+        sum += wd->history[i].x;
+        if (abs(wd->history[0].y - wd->history[i].y) > 10) return;
+     }
+
+   sum /= wd->movements;
+   if (abs(sum - wd->history[0].x) <= 10) return;
+   evas_object_smart_callback_call(it->base.widget, "swipe", it);
+}
+
+static void
+_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_List_Item *it = data;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   Evas_Event_Mouse_Down *ev = event_info;
+
+   if (!wd) return;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (ev->button != 1) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
+   else wd->on_hold = EINA_FALSE;
+   if (wd->on_hold) return;
+   wd->wasselected = it->selected;
+   _item_hilight(it);
+   wd->longpressed = EINA_FALSE;
+   if (it->long_timer) ecore_timer_del(it->long_timer);
+   it->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, it);
+   if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
+   it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
+   /* Always call the callbacks last - the user may delete our context! */
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     evas_object_smart_callback_call(it->base.widget, "clicked", it);
+   wd->swipe = EINA_FALSE;
+   wd->movements = 0;
+}
+
+static void
+_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_List_Item *it = data;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   Evas_Event_Mouse_Up *ev = event_info;
+
+   if (!wd) return;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (ev->button != 1) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
+   else wd->on_hold = EINA_FALSE;
+   wd->longpressed = EINA_FALSE;
+   if (it->long_timer)
+     {
+        ecore_timer_del(it->long_timer);
+        it->long_timer = NULL;
+     }
+   if (it->swipe_timer)
+     {
+        ecore_timer_del(it->swipe_timer);
+        it->swipe_timer = NULL;
+     }
+   if (wd->on_hold)
+     {
+        if (wd->swipe) _swipe(data);
+        wd->on_hold = EINA_FALSE;
+        return;
+     }
+   if (wd->longpressed)
+     {
+        if (!wd->wasselected) _item_unselect(it);
+        wd->wasselected = 0;
+        return;
+     }
+
+   if (it->disabled)
+     return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+  
+   _elm_list_walk(wd); // watch out "return" before unwalk!
+
+   if (wd->multi)
+     {
+        if (!it->selected)
+          {
+             _item_hilight(it);
+             _item_select(it);
+          }
+        else _item_unselect(it);
+     }
+   else
+     {
+        if (!it->selected)
+          {
+             while (wd->selected)
+                _item_unselect(wd->selected->data);
+             _item_hilight(it);
+             _item_select(it);
+          }
+        else
+          {
+             const Eina_List *l, *l_next;
+             Elm_List_Item *it2;
+
+             EINA_LIST_FOREACH_SAFE(wd->selected, l, l_next, it2)
+                if (it2 != it) _item_unselect(it2);
+             _item_hilight(it);
+             _item_select(it);
+          }
+     }
+
+   _elm_list_unwalk(wd);
+}
+
+static Elm_List_Item *
+_item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_List_Item *it;
+
+   if (!wd) return NULL;
+   it = elm_widget_item_new(obj, Elm_List_Item);
+   it->wd = wd;
+   it->label = eina_stringshare_add(label);
+   it->icon = icon;
+   it->end = end;
+   it->func = func;
+   it->base.data = data;
+   it->base.view = edje_object_add(evas_object_evas_get(obj));
+   evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _mouse_down, it);
+   evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_UP,
+                                  _mouse_up, it);
+   evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _mouse_move, it);
+   evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   if (it->icon)
+     {
+        elm_widget_sub_object_add(obj, it->icon);
+        evas_object_event_callback_add(it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _changed_size_hints, obj);
+     }
+   if (it->end)
+     {
+        elm_widget_sub_object_add(obj, it->end);
+        evas_object_event_callback_add(it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _changed_size_hints, obj);
+     }
+   return it;
+}
+
+static void
+_elm_list_mode_set_internal(Widget_Data *wd)
+{
+   if (!wd->scr)
+     return;
+
+   if (wd->mode == ELM_LIST_LIMIT)
+     {
+        if (!wd->h_mode)
+          {
+             wd->scr_minw = EINA_TRUE;
+             wd->scr_minh = EINA_FALSE;
+          }
+        else
+          {
+             wd->scr_minw = EINA_FALSE;
+             wd->scr_minh = EINA_TRUE;
+          }
+     }
+   else if (wd->mode == ELM_LIST_EXPAND)
+     {
+        wd->scr_minw = EINA_TRUE;
+        wd->scr_minh = EINA_TRUE;
+     }
+   else
+     {
+        wd->scr_minw = EINA_FALSE;
+        wd->scr_minh = EINA_FALSE;
+     }
+
+   _sizing_eval(wd->self);
+}
+
+static void
+_fix_items(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *l;
+   Elm_List_Item *it;
+   Evas_Coord minw[2] = { 0, 0 }, minh[2] = { 0, 0 };
+   Evas_Coord mw, mh;
+   int i, redo = 0;
+   const char *style = elm_widget_style_get(obj);
+   const char *it_plain = wd->h_mode ? "h_item" : "item";
+   const char *it_odd = wd->h_mode ? "h_item_odd" : "item_odd";
+   const char *it_compress = wd->h_mode ? "h_item_compress" : "item_compress";
+   const char *it_compress_odd = wd->h_mode ? "h_item_compress_odd" : "item_compress_odd";
+
+   if (!wd) return;
+   if (wd->walking)
+     {
+        wd->fix_pending = EINA_TRUE;
+        return;
+     }
+
+   _elm_list_walk(wd); // watch out "return" before unwalk!
+
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+        if (it->deleted) continue;
+        if (it->icon)
+          {
+             evas_object_size_hint_min_get(it->icon, &mw, &mh);
+             if (mw > minw[0]) minw[0] = mw;
+             if (mh > minh[0]) minh[0] = mh;
+          }
+        if (it->end)
+          {
+             evas_object_size_hint_min_get(it->end, &mw, &mh);
+             if (mw > minw[1]) minw[1] = mw;
+             if (mh > minh[1]) minh[1] = mh;
+          }
+     }
+
+   if ((minw[0] != wd->minw[0]) || (minw[1] != wd->minw[1]) ||
+       (minw[0] != wd->minh[0]) || (minh[1] != wd->minh[1]))
+     {
+        wd->minw[0] = minw[0];
+        wd->minw[1] = minw[1];
+        wd->minh[0] = minh[0];
+        wd->minh[1] = minh[1];
+        redo = 1;
+     }
+   i = 0;
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+       if (it->deleted)
+          continue;
+
+       it->even = i & 0x1;
+       if ((it->even != it->is_even) || (!it->fixed) || (redo))
+         {
+            const char *stacking;
+
+             /* FIXME: separators' themes seem to be b0rked */
+            if (it->is_separator)
+              _elm_theme_object_set(obj, it->base.view, "separator",
+                                     wd->h_mode ? "horizontal" : "vertical",
+                                     style);
+            else if (wd->mode == ELM_LIST_COMPRESS)
+              {
+                 if (it->even)
+                   _elm_theme_object_set(obj, it->base.view, "list",
+                                          it_compress, style);
+                 else
+                   _elm_theme_object_set(obj, it->base.view, "list",
+                                          it_compress_odd, style);
+              }
+            else
+              {
+                 if (it->even)
+                   _elm_theme_object_set(obj, it->base.view, "list", it_plain,
+                                          style);
+                 else
+                   _elm_theme_object_set(obj, it->base.view, "list", it_odd,
+                                          style);
+              }
+            stacking = edje_object_data_get(it->base.view, "stacking");
+            if (stacking)
+              {
+                 if (!strcmp(stacking, "below"))
+                   evas_object_lower(it->base.view);
+                 else if (!strcmp(stacking, "above"))
+                   evas_object_raise(it->base.view);
+              }
+            edje_object_part_text_set(it->base.view, "elm.text", it->label);
+
+            if ((!it->icon) && (minh[0] > 0))
+              {
+                 it->icon = evas_object_rectangle_add(evas_object_evas_get(it->base.view));
+                 evas_object_color_set(it->icon, 0, 0, 0, 0);
+                 it->dummy_icon = EINA_TRUE;
+              }
+            if ((!it->end) && (minh[1] > 0))
+              {
+                 it->end = evas_object_rectangle_add(evas_object_evas_get(it->base.view));
+                 evas_object_color_set(it->end, 0, 0, 0, 0);
+                 it->dummy_end = EINA_TRUE;
+              }
+            if (it->icon)
+              {
+                 evas_object_size_hint_min_set(it->icon, minw[0], minh[0]);
+                 evas_object_size_hint_max_set(it->icon, 99999, 99999);
+                 edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
+              }
+            if (it->end)
+              {
+                 evas_object_size_hint_min_set(it->end, minw[1], minh[1]);
+                 evas_object_size_hint_max_set(it->end, 99999, 99999);
+                 edje_object_part_swallow(it->base.view, "elm.swallow.end", it->end);
+              }
+            if (!it->fixed)
+              {
+                 // this may call up user and it may modify the list item
+                 // but we're safe as we're flagged as walking.
+                 // just don't process further
+                 edje_object_message_signal_process(it->base.view);
+                 if (it->deleted)
+                   continue;
+                 mw = mh = -1;
+                 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+                 edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh);
+                 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+                 evas_object_size_hint_min_set(it->base.view, mw, mh);
+                 evas_object_show(it->base.view);
+              }
+            if ((it->selected) || (it->hilighted))
+              {
+                 const char *selectraise;
+
+                 // this may call up user and it may modify the list item
+                 // but we're safe as we're flagged as walking.
+                 // just don't process further
+                 edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
+                 if (it->deleted)
+                   continue;
+
+                 selectraise = edje_object_data_get(it->base.view, "selectraise");
+                 if ((selectraise) && (!strcmp(selectraise, "on")))
+                   evas_object_raise(it->base.view);
+              }
+             if (it->disabled)
+               edje_object_signal_emit(it->base.view, "elm,state,disabled",
+                                       "elm");
+
+            it->fixed = EINA_TRUE;
+            it->is_even = it->even;
+         }
+       i++;
+     }
+
+   _elm_list_unwalk(wd);
+
+   mw = 0; mh = 0;
+   evas_object_size_hint_min_get(wd->box, &mw, &mh);
+
+   _elm_list_mode_set_internal(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;
+   if (wd->scr)
+     elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
+}
+
+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;
+   if (wd->scr)
+     elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
+}
+
+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;
+   if (wd->scr)
+     elm_smart_scroller_freeze_set(wd->scr, EINA_TRUE);
+}
+
+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;
+   if (wd->scr)
+     elm_smart_scroller_freeze_set(wd->scr, EINA_FALSE);
+}
+
+static void
+_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+/**
+ * Adds a list object.
+ *
+ * @param parent The parent object
+ * @return The created object or NULL upon failure
+ *
+ * @ingroup List
+ */
+EAPI Evas_Object *
+elm_list_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord minw, minh;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   wd->self = obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "list");
+   elm_widget_type_set(obj, "list");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->scr = elm_smart_scroller_add(e);
+   elm_smart_scroller_widget_set(wd->scr, obj);
+   _theme_hook(obj);
+   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(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);
+
+   elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
+                                       _elm_config->thumbscroll_bounce_enable);
+
+   wd->box = elm_box_add(parent);
+   elm_box_homogenous_set(wd->box, 1);
+   evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
+   elm_widget_on_show_region_hook_set(wd->box, _show_region_hook, obj);
+   elm_widget_sub_object_add(obj, wd->box);
+   elm_smart_scroller_child_set(wd->scr, wd->box);
+   evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                  _changed_size_hints, obj);
+
+   evas_object_show(wd->box);
+
+   wd->mode = ELM_LIST_SCROLL;
+
+   evas_object_smart_callback_add(wd->scr, "edge,left", _scroll_edge_left, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,right", _scroll_edge_right, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,top", _scroll_edge_top, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,bottom", _scroll_edge_bottom, 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);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Appends an item to the list object.
+ *
+ * @param obj The list object
+ * @param label The label of the list item
+ * @param icon The icon object to use for the left side of the item
+ * @param end The icon object to use for the right side of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item for related callbacks
+ *
+ * @return The created item or NULL upon failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
+
+   wd->items = eina_list_append(wd->items, it);
+   it->node = eina_list_last(wd->items);
+   elm_box_pack_end(wd->box, it->base.view);
+   return it;
+}
+
+/**
+ * Prepends an item to the list object.
+ *
+ * @param obj The list object
+ * @param label The label of the list item
+ * @param icon The icon object to use for the left side of the item
+ * @param end The icon object to use for the right side of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item for related callbacks
+ *
+ * @return The created item or NULL upon failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
+
+   wd->items = eina_list_prepend(wd->items, it);
+   it->node = wd->items;
+   elm_box_pack_start(wd->box, it->base.view);
+   return it;
+}
+
+/**
+ * Inserts an item into the list object before @p before.
+ *
+ * @param obj The list object
+ * @param before The list item to insert before
+ * @param label The label of the list item
+ * @param icon The icon object to use for the left side of the item
+ * @param end The icon object to use for the right side of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item for related callbacks
+ *
+ * @return The created item or NULL upon failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_item_insert_before(Evas_Object *obj, Elm_List_Item *before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
+{
+   Widget_Data *wd;
+   Elm_List_Item *it;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
+   if (!before->node) return NULL;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(before, NULL);
+
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   it = _item_new(obj, label, icon, end, func, data);
+   wd->items = eina_list_prepend_relative_list(wd->items, it, before->node);
+   it->node = before->node->prev;
+   elm_box_pack_before(wd->box, it->base.view, before->base.view);
+   return it;
+}
+
+/**
+ * Inserts an item into the list object after @p after.
+ *
+ * @param obj The list object
+ * @param after The list item to insert after
+ * @param label The label of the list item
+ * @param icon The icon object to use for the left side of the item
+ * @param end The icon object to use for the right side of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item for related callbacks
+ *
+ * @return The created item or NULL upon failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_item_insert_after(Evas_Object *obj, Elm_List_Item *after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
+{
+   Widget_Data *wd;
+   Elm_List_Item *it;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
+   if (!after->node) return NULL;
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(after, NULL);
+
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   it = _item_new(obj, label, icon, end, func, data);
+   wd->items = eina_list_append_relative_list(wd->items, it, after->node);
+   it->node = after->node->next;
+   elm_box_pack_after(wd->box, it->base.view, after->base.view);
+   return it;
+}
+
+/**
+ * Insert a new item into the sorted list object.
+ *
+ * @param obj The list object
+ * @param label The label of the list item
+ * @param icon The icon object to use for the left side of the item
+ * @param end The icon object to use for the right side of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item for related callbacks
+ * @param cmp_func The function called for the sort.
+ *
+ * @return The created item or NULL upon failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_item_sorted_insert(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
+   Eina_List *l;
+
+   wd->items = eina_list_sorted_insert(wd->items, cmp_func, it);
+   l = eina_list_data_find_list(wd->items, it);
+   l = eina_list_next(l);
+   if (!l)
+     {
+        it->node = eina_list_last(wd->items);
+        elm_box_pack_end(wd->box, it->base.view);
+     }
+   else
+     {
+        Elm_List_Item *before = eina_list_data_get(l);
+        it->node = before->node->prev;
+        elm_box_pack_before(wd->box, it->base.view, before->base.view);
+     }
+   return it;
+}
+
+/**
+ * Clears a list of all items.
+ *
+ * @param obj The list object
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_clear(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_List_Item *it;
+
+   if (!wd) return;
+   if (!wd->items) return;
+
+   eina_list_free(wd->selected);
+   wd->selected = NULL;
+
+   if (wd->walking > 0)
+     {
+        Eina_List *n;
+
+        EINA_LIST_FOREACH(wd->items, n, it)
+          {
+             if (it->deleted) continue;
+             it->deleted = EINA_TRUE;
+             wd->to_delete = eina_list_append(wd->to_delete, it);
+          }
+        return;
+     }
+
+   _elm_list_walk(wd);
+
+   EINA_LIST_FREE(wd->items, it)
+     {
+        elm_widget_item_pre_notify_del(it);
+        _elm_list_item_free(it);
+     }
+
+   _elm_list_unwalk(wd);
+
+   _fix_items(obj);
+   _sizing_eval(obj);
+}
+
+/**
+ * Starts the list.  Call before running show() on the list object.
+ *
+ * @param obj The list object
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_go(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _fix_items(obj);
+}
+
+/**
+ * Enables/disables the state of multi-select on the list object.
+ *
+ * @param obj The list object
+ * @param multi If true, multi-select is enabled
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_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;
+}
+
+/**
+ * Gets the state of multi-select on the list object.
+ *
+ * @param obj The list object
+ * @return If true, multi-select is enabled
+ *
+ * @ingroup List
+ */
+EAPI Eina_Bool
+elm_list_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;
+}
+
+/**
+ * Set which mode to use for the list with.
+ *
+ * @param obj The list object
+ * @param mode One of @c ELM_LIST_COMPRESS, @c ELM_LIST_SCROLL, @c
+ *             ELM_LIST_LIMIT or @c ELM_LIST_EXPAND.
+ *
+ * @note Default value is @c ELM_LIST_SCROLL. At this mode, the list
+ * object won't set any of its size hints to inform how a possible
+ * container should resize it. Then, if it's not created as a "resize
+ * object", it might end with zero dimensions. The list will respect
+ * the container's geometry and, if any of its items won't fit into
+ * its transverse axis, one will be able to scroll it in that
+ * direction. @c ELM_LIST_COMPRESS is the same as the previous, except
+ * that it <b>won't</b> let one scroll in the transverse axis, on
+ * those cases (large items will get cropped). @c ELM_LIST_LIMIT will
+ * actually set a minimun size hint on the list object, so that
+ * containers may respect it (and resize itself to fit the child
+ * properly). More specifically, a minimum size hint will be set for
+ * its transverse axis, so that the <b>largest</b> item in that
+ * direction fits well. @c ELM_LIST_EXPAND, besides setting a minimum
+ * size on the transverse axis, just like the previous mode, will set
+ * a minimum size on the longitudinal axis too, trying to reserve
+ * space to all its children to be visible at a time. The last two
+ * modes can always have effects bounded by setting the list object's
+ * maximum size hints, though.
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+   if (wd->mode == mode)
+     return;
+   wd->mode = mode;
+
+   _elm_list_mode_set_internal(wd);
+}
+
+/**
+ * Get the mode the list is at.
+ *
+ * @param obj The list object
+ * @return mode One of @c ELM_LIST_COMPRESS, @c ELM_LIST_SCROLL or @c
+ *         ELM_LIST_LIMIT (@c ELM_LIST_LAST on errors).
+ *
+ * @note see elm_list_mode_set() for more information.
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Mode
+elm_list_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_LIST_LAST;
+   return wd->mode;
+}
+
+/**
+ * Enables/disables horizontal mode of the list.
+ *
+ * @param obj The list object
+ * @param mode If true, horizontale mode is enabled
+ *
+ * @note Bounce options for the list will be reset to default values
+ * with this funcion. Re-call elm_list_bounce_set() once more after
+ * this one, if you had custom values.
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   Widget_Data *wd;
+   Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return;
+
+   if (wd->h_mode == horizontal)
+     return;
+
+   wd->h_mode = horizontal;
+   elm_box_horizontal_set(wd->box, horizontal);
+
+   if (horizontal)
+     {
+        evas_object_size_hint_weight_set(wd->box, 0.0, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(wd->box, 0.0, EVAS_HINT_FILL);
+        elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
+     }
+   else
+     {
+        evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
+        evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
+        elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE, bounce);
+     }
+
+   _elm_list_mode_set_internal(wd);
+}
+
+/**
+ * Retrieve whether horizontal mode is enabled for a list.
+ *
+ * @param obj The list object
+ * @return @c EINA_TRUE, if horizontal mode is enabled and @c
+ *            EINA_FALSE, otherwise.
+ *
+ * @note see elm_list_horizontal_set() for more information.
+ *
+ * @ingroup List
+ */
+EAPI Eina_Bool
+elm_list_horizontal_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     return EINA_FALSE;
+
+   return wd->h_mode;
+}
+
+/**
+ * Enables/disables the state of always_select, meaning that
+ * an item will always be selected.
+ *
+ * @param obj The list object
+ * @param always_select If true, always_select is enabled
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_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;
+}
+
+/**
+ * Gets the state of always_select.
+ * See also elm_list_always_select_mode_set()
+ *
+ * @param obj The list object
+ * @return If true, always_select is enabled
+ *
+ * @ingroup List
+ */
+EAPI Eina_Bool
+elm_list_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;
+}
+
+/**
+ * Returns a list of all the list items.
+ *
+ * @param obj The list object
+ * @return An Eina_List* of the list items, or NULL on failure
+ *
+ * @ingroup List
+ */
+EAPI const Eina_List *
+elm_list_items_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->items;
+}
+
+/**
+ * Returns the currently selected list item.
+ *
+ * @param obj The list object
+ * @return The selected list item, or NULL on failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_selected_item_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;
+}
+
+/**
+ * Returns a list of the currently selected list items.
+ *
+ * @param obj The list object
+ * @return An Eina_List* of the selected list items, or NULL on failure
+ *
+ * @ingroup List
+ */
+EAPI const Eina_List *
+elm_list_selected_items_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;
+}
+
+/**
+ * Sets if item is a separator.
+ *
+ * @param it The list item object
+ * @param setting
+ */
+EAPI void
+elm_list_item_separator_set(Elm_List_Item *it, Eina_Bool setting)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   it->is_separator = !!setting;
+}
+
+/**
+ * Returns EINA_TRUE if Elm_List_Item is a separator.
+ *
+ * @param it The list item object
+ */
+EAPI Eina_Bool
+elm_list_item_separator_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
+   return it->is_separator;
+}
+
+
+/**
+ * Sets the selected state of @p it.
+ *
+ * @param it The list item
+ * @param selected Enables/disables the selected state
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_selected_set(Elm_List_Item *it, Eina_Bool selected)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   if (!wd) return;
+
+   selected = !!selected;
+   if (it->selected == selected) return;
+
+   _elm_list_walk(wd);
+
+   if (selected)
+     {
+        if (!wd->multi)
+          {
+             while (wd->selected)
+                _item_unselect(wd->selected->data);
+          }
+        _item_hilight(it);
+        _item_select(it);
+     }
+   else
+      _item_unselect(it);
+
+   _elm_list_unwalk(wd);
+}
+
+/**
+ * Gets the selected state of @p it.
+ *
+ * @param it The list item
+ * @return If true, the item is selected
+ *
+ * @ingroup List
+ */
+EAPI Eina_Bool
+elm_list_item_selected_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
+   return it->selected;
+}
+
+/**
+ * Brings @p it to the center of the list view.
+ *
+ * @param it The list item
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_show(Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   Evas_Coord bx, by, bw, bh;
+   Evas_Coord x, y, w, h;
+
+   evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
+   evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
+   x -= bx;
+   y -= by;
+   if (wd->scr)
+     elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
+}
+
+/**
+ * Bring in the given item
+ *
+ * This causes list to jump to the given item @p it and show it (by scrolling),
+ * if it is not fully visible. This may use animation to do so and take a
+ * period of time
+ *
+ * @param it The item
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_bring_in(Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   Evas_Coord bx, by, bw, bh;
+   Evas_Coord x, y, w, h;
+
+   evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
+   evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
+   x -= bx;
+   y -= by;
+   if (wd->scr)
+     elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
+}
+
+/**
+ * Deletes item @p it from the list.
+ *
+ * @param it The list item to delete
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_del(Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   if (!wd) return;
+
+   if (it->selected) _item_unselect(it);
+
+   if (wd->walking > 0)
+     {
+        if (it->deleted) return;
+        it->deleted = EINA_TRUE;
+        wd->to_delete = eina_list_append(wd->to_delete, it);
+        return;
+     }
+
+   wd->items = eina_list_remove_list(wd->items, it->node);
+
+   _elm_list_walk(wd);
+
+   elm_widget_item_pre_notify_del(it);
+   _elm_list_item_free(it);
+
+   _elm_list_unwalk(wd);
+}
+
+/**
+ * Set the function called when a list item is freed.
+ *
+ * @param it The item to set the callback on
+ * @param func The function called
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_del_cb_set(Elm_List_Item *it, Evas_Smart_Cb func)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   elm_widget_item_del_cb_set(it, func);
+}
+
+/**
+ * Returns the data associated with the item.
+ *
+ * @param it The list item
+ * @return The data associated with @p it
+ *
+ * @ingroup List
+ */
+EAPI void *
+elm_list_item_data_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
+   return elm_widget_item_data_get(it);
+}
+
+/**
+ * Returns the left side icon associated with the item.
+ *
+ * @param it The list item
+ * @return The left side icon associated with @p it
+ *
+ * @ingroup List
+ */
+EAPI Evas_Object *
+elm_list_item_icon_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
+   if (it->dummy_icon) return NULL;
+   return it->icon;
+}
+
+/**
+ * Sets the left side icon associated with the item.
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * You probably don't want, then, to have the <b>same</b> icon object set
+ * for more than one item of the list.
+ *
+ * @param it The list item
+ * @param icon The left side icon object to associate with @p it
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_icon_set(Elm_List_Item *it, Evas_Object *icon)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (it->icon == icon) return;
+   if ((it->dummy_icon) && (!icon)) return;
+   if (it->dummy_icon)
+     {
+        evas_object_del(it->icon);
+        it->dummy_icon = EINA_FALSE;
+     }
+   if (!icon)
+     {
+        icon = evas_object_rectangle_add(evas_object_evas_get(it->base.widget));
+        evas_object_color_set(icon, 0, 0, 0, 0);
+        it->dummy_icon = EINA_TRUE;
+     }
+   if (it->icon)
+     {
+        evas_object_del(it->icon);
+        it->icon = NULL;
+     }
+   it->icon = icon;
+   if (it->base.view)
+     edje_object_part_swallow(it->base.view, "elm.swallow.icon", icon);
+}
+
+/**
+ * Gets the right side icon associated with the item.
+ *
+ * @param it The list item
+ * @return The right side icon object associated with @p it
+ *
+ * @ingroup List
+ */
+EAPI Evas_Object *
+elm_list_item_end_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
+   if (it->dummy_end) return NULL;
+   return it->end;
+}
+
+/**
+ * Sets the right side icon associated with the item.
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * You probably don't want, then, to have the <b>same</b> icon object set
+ * for more than one item of the list.
+ *
+ * @param it The list item
+ * @param icon The right side icon object to associate with @p it
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_end_set(Elm_List_Item *it, Evas_Object *end)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (it->end == end) return;
+   if ((it->dummy_end) && (!end)) return;
+   if (it->dummy_end)
+     {
+        evas_object_del(it->end);
+        it->dummy_icon = EINA_FALSE;
+     }
+   if (!end)
+     {
+        end = evas_object_rectangle_add(evas_object_evas_get(it->base.widget));
+        evas_object_color_set(end, 0, 0, 0, 0);
+        it->dummy_end = EINA_TRUE;
+     }
+   if (it->end)
+     {
+        evas_object_del(it->end);
+        it->end = NULL;
+     }
+   it->end = end;
+   if (it->base.view)
+     edje_object_part_swallow(it->base.view, "elm.swallow.end", end);
+}
+
+/**
+ * Gets the base object of the item.
+ *
+ * @param it The list item
+ * @return The base object associated with @p it
+ *
+ * @ingroup List
+ */
+EAPI Evas_Object *
+elm_list_item_base_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
+   return it->base.view;
+}
+
+/**
+ * Gets the label of the item.
+ *
+ * @param it The list item
+ * @return The label of @p it
+ *
+ * @ingroup List
+ */
+EAPI const char *
+elm_list_item_label_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
+   return it->label;
+}
+
+/**
+ * Sets the label of the item.
+ *
+ * @param it The list item
+ * @param text The label of @p it
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_label_set(Elm_List_Item *it, const char *text)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+   if (!eina_stringshare_replace(&it->label, text)) return;
+   if (it->base.view)
+     edje_object_part_text_set(it->base.view, "elm.text", it->label);
+}
+
+/**
+ * Gets the item before @p it in the list.
+ *
+ * @param it The list item
+ * @return The item before @p it, or NULL on failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_item_prev(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
+   if (it->node->prev) return it->node->prev->data;
+   else return NULL;
+}
+
+/**
+ * Gets the item after @p it in the list.
+ *
+ * @param it The list item
+ * @return The item after @p it, or NULL on failure
+ *
+ * @ingroup List
+ */
+EAPI Elm_List_Item *
+elm_list_item_next(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
+   if (it->node->next) return it->node->next->data;
+   else return NULL;
+}
+
+/**
+ * Set the text to be shown in the list item.
+ *
+ * @param item Target item
+ * @param text The text to set in the content
+ *
+ * Setup the text as tooltip to object. The item can have only one tooltip,
+ * so any previous tooltip data is removed.
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_tooltip_text_set(Elm_List_Item *item, const char *text)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_tooltip_text_set(item, text);
+}
+
+/**
+ * Set the content to be shown in the tooltip item
+ *
+ * Setup the tooltip to item. The item can have only one tooltip,
+ * so any previous tooltip data is removed. @p func(with @p data) will
+ * be called every time that need show the tooltip and it should
+ * return a valid Evas_Object. This object is then managed fully by
+ * tooltip system and is deleted when the tooltip is gone.
+ *
+ * @param item the list item being attached a tooltip.
+ * @param func the function used to create the tooltip contents.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_list_item_tooltip_unset() or the owner @a item
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is the item.
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_tooltip_content_cb_set(Elm_List_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
+}
+
+/**
+ * Unset tooltip from item
+ *
+ * @param item list item to remove previously set tooltip.
+ *
+ * Remove tooltip from item. The callback provided as del_cb to
+ * elm_list_item_tooltip_content_cb_set() will be called to notify
+ * it is not used anymore.
+ *
+ * @see elm_list_item_tooltip_content_cb_set()
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_tooltip_unset(Elm_List_Item *item)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_tooltip_unset(item);
+}
+
+/**
+ * Sets a different style for this item tooltip.
+ *
+ * @note before you set a style you should define a tooltip with
+ *       elm_list_item_tooltip_content_cb_set() or
+ *       elm_list_item_tooltip_text_set()
+ *
+ * @param item list item with tooltip already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_tooltip_style_set(Elm_List_Item *item, const char *style)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_tooltip_style_set(item, style);
+}
+
+/**
+ * Get the style for this item tooltip.
+ *
+ * @param item list item with tooltip already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a tooltip set, then NULL is returned.
+ *
+ * @ingroup List
+ */
+EAPI const char *
+elm_list_item_tooltip_style_get(const Elm_List_Item *item)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
+   return elm_widget_item_tooltip_style_get(item);
+}
+
+/**
+ * Set the cursor to be shown when mouse is over the list item
+ *
+ * @param item Target item
+ * @param cursor the cursor name to be used.
+ *
+ * @see elm_object_cursor_set()
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_cursor_set(Elm_List_Item *item, const char *cursor)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_cursor_set(item, cursor);
+}
+
+/**
+ * Get the cursor to be shown when mouse is over the list item
+ *
+ * @param item list item with cursor already set.
+ * @return the cursor name.
+ *
+ * @ingroup List
+ */
+EAPI const char *
+elm_list_item_cursor_get(const Elm_List_Item *item)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
+   return elm_widget_item_cursor_get(item);
+}
+
+/**
+ * Unset the cursor to be shown when mouse is over the list item
+ *
+ * @param item Target item
+ *
+ * @see elm_object_cursor_unset()
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_cursor_unset(Elm_List_Item *item)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_cursor_unset(item);
+}
+
+/**
+ * Sets a different style for this item cursor.
+ *
+ * @note before you set a style you should define a cursor with
+ *       elm_list_item_cursor_set()
+ *
+ * @param item list item with cursor already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_cursor_style_set(Elm_List_Item *item, const char *style)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_cursor_style_set(item, style);
+}
+
+/**
+ * Get the style for this item cursor.
+ *
+ * @param item list item with cursor already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup List
+ */
+EAPI const char *
+elm_list_item_cursor_style_get(const Elm_List_Item *item)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
+   return elm_widget_item_cursor_style_get(item);
+}
+
+/**
+ * Set if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a cursor
+ * with elm_object_cursor_set(). By default it will only look for cursors
+ * provided by the engine.
+ *
+ * @param item widget item with cursor already set.
+ * @param engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well.
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_cursor_engine_only_set(Elm_List_Item *item, Eina_Bool engine_only)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
+   elm_widget_item_cursor_engine_only_set(item, engine_only);
+}
+
+/**
+ * Get the cursor engine only usage for this item cursor.
+ *
+ * @param item widget item with cursor already set.
+ * @return engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well. If
+ *         the object does not have a cursor set, then EINA_FALSE is returned.
+ *
+ * @ingroup List
+ */
+EAPI Eina_Bool
+elm_list_item_cursor_engine_only_get(const Elm_List_Item *item)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
+   return elm_widget_item_cursor_engine_only_get(item);
+}
+
+/**
+ * Set bounce mode
+ *
+ * This will enable or disable the scroller bounce mode for the list. See
+ * elm_scroller_bounce_set() for details
+ *
+ * @param obj The list object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_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;
+   if (wd->scr)
+     elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
+}
+
+/**
+ * Get the bounce mode
+ *
+ * @param obj The List object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_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);
+}
+
+/**
+ * Set the scrollbar policy
+ *
+ * This sets the scrollbar visibility policy for the given list 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 list object
+ * @param policy_h Horizontal scrollbar policy
+ * @param policy_v Vertical scrollbar policy
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
+       (policy_v >= ELM_SCROLLER_POLICY_LAST))
+   if (wd->scr)
+     elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
+}
+
+EAPI void
+elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
+   if ((!wd) || (!wd->scr)) return;
+   elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
+   if (policy_h) *policy_h = (Elm_Scroller_Policy) s_policy_h;
+   if (policy_v) *policy_v = (Elm_Scroller_Policy) s_policy_v;
+}
+
+/**
+ * Sets the disabled/enabled state of a list item.
+ *
+ * A disabled item cannot be selected or unselected. It will also
+ * change its appearance (generally greyed out). This sets the
+ * disabled state (@c EINA_TRUE for disabled, @c EINA_FALSE for
+ * enabled).
+ *
+ * @param it The item
+ * @param disabled The disabled state
+ *
+ * @ingroup List
+ */
+EAPI void
+elm_list_item_disabled_set(Elm_List_Item *it, Eina_Bool disabled)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
+
+   if (it->disabled == disabled)
+     return;
+
+   it->disabled = !!disabled;
+
+   if (it->disabled)
+     edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
+   else
+     edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
+}
+
+/**
+ * Get the disabled/enabled state of a list item
+ *
+ * @param it The item
+ * @return The disabled state
+ *
+ * See elm_list_item_disabled_set().
+ *
+ * @ingroup List
+ */
+EAPI Eina_Bool
+elm_list_item_disabled_get(const Elm_List_Item *it)
+{
+   ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
+
+   return it->disabled;
+}
diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c
new file mode 100644 (file)
index 0000000..6237ec8
--- /dev/null
@@ -0,0 +1,3430 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <dlfcn.h> /* dlopen,dlclose,etc */
+
+#ifdef HAVE_CRT_EXTERNS_H
+# include <crt_externs.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define SEMI_BROKEN_QUICKLAUNCH 1
+
+static Elm_Version _version = { VMAJ, VMIN, VMIC, VREV };
+EAPI Elm_Version *elm_version = &_version;
+
+Eina_Bool
+_elm_dangerous_call_check(const char *call)
+{
+   char buf[256];
+   const char *eval;
+
+   snprintf(buf, sizeof(buf), "%i.%i.%i.%i", VMAJ, VMIN, VMIC, VREV);
+   eval = getenv("ELM_NO_FINGER_WAGGLING");
+   if ((eval) && (!strcmp(eval, buf)))
+     return 0;
+   printf("ELEMENTARY FINGER WAGGLE!!!!!!!!!!\n"
+          "\n"
+          "  %s() used.\n"
+          "PLEASE see the API documentation for this function. This call\n"
+          "should almost never be used. Only in very special cases.\n"
+          "\n"
+          "To remove this warning please set the environment variable:\n"
+          "  ELM_NO_FINGER_WAGGLING\n"
+          "To the value of the Elementary version + revision number. e.g.:\n"
+          "  1.2.5.40295\n"
+          "\n"
+          ,
+          call);
+   return 1;
+}
+
+/**
+ * @defgroup Start Getting Started
+ *
+ * To write an Elementary app, you can get started with the following:
+ *
+ * @code
+ * #include <Elementary.h>
+ * #ifndef ELM_LIB_QUICKLAUNCH
+ * EAPI int
+ * elm_main(int argc, char **argv)
+ * {
+ *    // create window(s) here and do any application init
+ *    elm_run(); // run main loop
+ *    elm_shutdown(); // after mainloop finishes running, shutdown
+ *    return 0; // exit 0 for exit code
+ * }
+ * #endif
+ * ELM_MAIN()
+ * @endcode
+ *
+ * To take full advantage of the quicklaunch architecture for launching
+ * processes as quickly as possible (saving time at startup time like
+ * connecting to X11, loading and linking shared libraries) you may want to
+ * use the following configure.in/configure.ac and Makefile.am and autogen.sh
+ * script to generate your files. It is assumed your application uses the
+ * main.c file for its code.
+ *
+ * configure.in/configure.ac:
+ *
+@verbatim
+AC_INIT(myapp, 0.0.0, myname@mydomain.com)
+AC_PREREQ(2.52)
+AC_CONFIG_SRCDIR(configure.in)
+
+AM_INIT_AUTOMAKE(1.6 dist-bzip2)
+AM_CONFIG_HEADER(config.h)
+
+AC_C_BIGENDIAN
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+AC_C_CONST
+
+AC_LIBTOOL_WIN32_DLL
+define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
+define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
+AC_PROG_LIBTOOL
+
+PKG_CHECK_MODULES([ELEMENTARY], elementary)
+
+AC_OUTPUT(Makefile)
+@endverbatim
+ *
+ * Makefile.am:
+ *
+@verbatim
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir) @ELEMENTARY_CFLAGS@
+
+bin_PROGRAMS      = myapp
+myapp_LTLIBRARIES = myapp.la
+
+myappdir = $(libdir)
+
+myapp_la_SOURCES = main.c
+myapp_la_LIBADD = @ELEMENTARY_LIBS@
+myapp_la_CFLAGS =
+myapp_la_LDFLAGS = -module -avoid-version -no-undefined
+
+myapp_SOURCES = main.c
+myapp_LDADD = @ELEMENTARY_LIBS@
+myapp_CFLAGS = -DELM_LIB_QUICKLAUNCH=1
+@endverbatim
+ *
+ * autogen.sh:
+ *
+@verbatim
+#!/bin/sh
+rm -rf autom4te.cache
+rm -f aclocal.m4 ltmain.sh
+rm -rf m4
+mkdir m4
+
+touch README
+echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1
+echo "Running autoheader..." ; autoheader || exit 1
+echo "Running autoconf..." ; autoconf || exit 1
+echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
+echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
+
+if [ -z "$NOCONFIGURE" ]; then
+  ./configure "$@"
+fi
+@endverbatim
+ *
+ * To gnerate all the things needed to bootstrap just run:
+ *
+@verbatim
+./autogen.sh
+@endverbatim
+ *
+ * This will generate Makefile.in's, the confgure script and everything else.
+ * After this it works like all normal autotools projects:
+@verbatim
+./configure
+make
+sudo make install
+@endverbatim
+ *
+ * Note sudo was assumed to get root permissions, as this would install in
+ * /usr/local which is system-owned. Ue any way you like to gain root, or
+ * specify a different prefix with configure:
+ *
+@verbatim
+./confiugre --prefix=$HOME/mysoftware
+@endverbatim
+ *
+ * Also remember that autotools buys you some useful commands like:
+@verbatim
+make uninstall
+@endverbatim
+ *
+ * This uninstalls the software after it was installed with "make install".
+ * It is very useful to clear up what you built if you wish to clean the
+ * system.
+ *
+@verbatim
+make distcheck
+@endverbatim
+ *
+ * This firstly checks if your build tree is "clean" and ready for
+ * distribution. It also builds a tarball (myapp-0.0.0.tar.gz) that is
+ * ready to upload and distribute to the world, that contains the generated
+ * Makefile.in's and configure script. The users do not need to run
+ * autogen.sh - just configure and on. They don't need autotools installed.
+ * This tarball also builds cleanly, has all the sources it needs to build
+ * included (that is sources for your application, not libraries it depends
+ * on like Elementary). It builds cleanly in a buildroot and does not
+ * contain any files that are temporarily generated like binaries and other
+ * build-gnerated files, so the tarball is clean, and no need to worry
+ * about cleaning up your tree before packaging.
+ *
+@verbatim
+make clean
+@endverbatim
+ *
+ * This cleans up all build files (binaries, objects etc.) from the tree.
+ *
+@verbatim
+make distclean
+@endverbatim
+ *
+ * This cleans out all files from the build and from configure's output too.
+ *
+@verbatim
+make maintainer-clean
+@endverbatim
+ *
+ * This deletes all the files autogen.sh will produce so the tree is clean
+ * to be put into a revision-control system (like CVS, SVN or GIT for example).
+ *
+ * The above will build a library - libmyapp.so and install in the target
+ * library directory (default is /usr/local/lib). You will also get a
+ * myapp.a and myapp.la - these are useless and can be deleted. Libtool likes
+ * to generate these all the time. You will also get a binary in the target
+ * binary directory (default is /usr/local/bin). This is a "debug binary".
+ * This will run and dlopen() the myapp.so and then jump to it's elm_main
+ * function. This allows for easy debugging with GDB and Valgrind. When you
+ * are ready to go to production do the following:
+ *
+ * 1. delete the myapp binary. i.e. rm /usr/local/bin/myapp
+ *
+ * 2. symlink the myapp binary to elementary_run (supplied by elementary).
+ * i.e. ln -s elmentary_run /usr/local/bin/myapp
+ *
+ * 3. run elementary_quicklaunch as part of your graphical login session and
+ * keep it running.
+ *
+ * This will man elementary_quicklaunch does pre-initialization before the
+ * application needs to be run, saving the effort at the time the application
+ * is needed, thus speeding up the time it takes to appear.
+ *
+ * If you don't want to use the quicklaunch infrastructure (which is
+ * optional), you can execute the old fashioned way by just running the
+ * myapp binary loader than will load the myapp.so for you, or you can
+ * remove the split-file binary and put it into one binary as things always
+ * have been with the following configure.in/configure.ac and Makfile.am
+ * files:
+ *
+ * configure.in/configure.ac:
+ *
+@verbatim
+AC_INIT(myapp, 0.0.0, myname@mydomain.com)
+AC_PREREQ(2.52)
+AC_CONFIG_SRCDIR(configure.in)
+
+AM_INIT_AUTOMAKE(1.6 dist-bzip2)
+AM_CONFIG_HEADER(config.h)
+
+AC_C_BIGENDIAN
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+AC_C_CONST
+
+PKG_CHECK_MODULES([ELEMENTARY], elementary)
+
+AC_OUTPUT(Makefile)
+@endverbatim
+ *
+ * Makefile.am:
+ *
+@verbatim
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir) @ELEMENTARY_CFLAGS@
+
+bin_PROGRAMS      = myapp
+
+myapp_SOURCES = main.c
+myapp_LDADD = @ELEMENTARY_LIBS@
+myapp_CFLAGS =
+@endverbatim
+ *
+ * Notice that they are the same as before, just with libtool and library
+ * building sections removed. Both ways work for building elementary
+ * applications. It is up to you to decide what is best for you. If you just
+ * follow the template above, you can do it both ways and can decide at build
+ * time. The more advanced of you may suggest making it a configure option.
+ * That is perfectly valid, but has been left out here for simplicity, as our
+ * aim to have an Elementary (and EFL) tutorial, not an autoconf & automake
+ * document.
+ *
+ */
+
+static Eina_Bool _elm_signal_exit(void *data,
+                                  int   ev_type,
+                                  void *ev);
+
+char *_elm_appname = NULL;
+const char *_elm_data_dir = NULL;
+const char *_elm_lib_dir = NULL;
+int _elm_log_dom = -1;
+
+EAPI int ELM_EVENT_POLICY_CHANGED = 0;
+
+static int _elm_init_count = 0;
+static int _elm_sub_init_count = 0;
+static int _elm_ql_init_count = 0;
+static int _elm_policies[ELM_POLICY_LAST];
+static Ecore_Event_Handler *_elm_exit_handler = NULL;
+static Eina_Bool quicklaunch_on = 0;
+
+static Eina_Bool
+_elm_signal_exit(void *data  __UNUSED__,
+                 int ev_type __UNUSED__,
+                 void *ev    __UNUSED__)
+{
+   elm_exit();
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+void
+_elm_rescale(void)
+{
+   edje_scale_set(_elm_config->scale);
+   _elm_win_rescale(NULL, EINA_FALSE);
+}
+
+/**
+ * @defgroup General General
+ */
+
+/**
+ * Inititalise Elementary
+ *
+ * @return The init counter value.
+ *
+ * This call is exported only for use by the ELM_MAIN() macro. There is no
+ * need to use this if you use this macro (which is highly advisable).
+ * @ingroup General
+ */
+EAPI int
+elm_init(int    argc,
+         char **argv)
+{
+   _elm_init_count++;
+   if (_elm_init_count > 1) return _elm_init_count;
+   elm_quicklaunch_init(argc, argv);
+   elm_quicklaunch_sub_init(argc, argv);
+   return _elm_init_count;
+}
+
+/**
+ * Shut down Elementary
+ *
+ * @return The init counter value.
+ *
+ * This should be called at the end of your application just before it ceases
+ * to do any more processing. This will clean up any permanent resources your
+ * application may have allocated via Elementary that would otherwise persist
+ * on an exit without this call.
+ * @ingroup General
+ */
+EAPI int
+elm_shutdown(void)
+{
+   _elm_init_count--;
+   if (_elm_init_count > 0) return _elm_init_count;
+   elm_quicklaunch_sub_shutdown();
+   elm_quicklaunch_shutdown();
+   return _elm_init_count;
+}
+
+#ifdef ELM_EDBUS
+static int _elm_need_e_dbus = 0;
+#endif
+EAPI Eina_Bool
+elm_need_e_dbus(void)
+{
+#ifdef ELM_EDBUS
+   if (_elm_need_e_dbus++) return EINA_TRUE;
+   e_dbus_init();
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+static void
+_elm_unneed_e_dbus(void)
+{
+#ifdef ELM_EDBUS
+   if (--_elm_need_e_dbus) return;
+
+   _elm_need_e_dbus = 0;
+   e_dbus_shutdown();
+#endif
+}
+
+#ifdef ELM_EFREET
+static int _elm_need_efreet = 0;
+#endif
+EAPI Eina_Bool
+elm_need_efreet(void)
+{
+#ifdef ELM_EFREET
+   if (_elm_need_efreet++) return EINA_TRUE;
+   efreet_init();
+   efreet_mime_init();
+   efreet_trash_init();
+    /*
+     {
+        Eina_List **list;
+
+        list = efreet_icon_extra_list_get();
+        if (list)
+          {
+             e_user_dir_concat_static(buf, "icons");
+             *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
+             e_prefix_data_concat_static(buf, "data/icons");
+             *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
+          }
+     }
+   */
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+static void
+_elm_unneed_efreet(void)
+{
+#ifdef ELM_EFREET
+   if (--_elm_need_efreet) return;
+
+   _elm_need_efreet = 0;
+   efreet_trash_shutdown();
+   efreet_mime_shutdown();
+   efreet_shutdown();
+#endif
+}
+
+EAPI void
+elm_quicklaunch_mode_set(Eina_Bool ql_on)
+{
+   quicklaunch_on = ql_on;
+}
+
+EAPI Eina_Bool
+elm_quicklaunch_mode_get(void)
+{
+   return quicklaunch_on;
+}
+
+EAPI int
+elm_quicklaunch_init(int    argc,
+                     char **argv)
+{
+   char buf[PATH_MAX], *s;
+
+   _elm_ql_init_count++;
+   if (_elm_ql_init_count > 1) return _elm_ql_init_count;
+   eina_init();
+   _elm_log_dom = eina_log_domain_register("elementary", EINA_COLOR_LIGHTBLUE);
+   if (!_elm_log_dom)
+     {
+        EINA_LOG_ERR("could not register elementary log domain.");
+        _elm_log_dom = EINA_LOG_DOMAIN_GLOBAL;
+     }
+
+   eet_init();
+   ecore_init();
+   ecore_app_args_set(argc, (const char **)argv);
+
+   memset(_elm_policies, 0, sizeof(_elm_policies));
+   if (!ELM_EVENT_POLICY_CHANGED)
+     ELM_EVENT_POLICY_CHANGED = ecore_event_type_new();
+
+   ecore_file_init();
+
+   _elm_exit_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, _elm_signal_exit, NULL);
+
+   if (argv) _elm_appname = strdup(ecore_file_file_get(argv[0]));
+
+   if (!_elm_data_dir)
+     {
+        s = getenv("ELM_DATA_DIR");
+        _elm_data_dir = eina_stringshare_add(s);
+     }
+   if (!_elm_data_dir)
+     {
+        s = getenv("ELM_PREFIX");
+        if (s)
+          {
+             snprintf(buf, sizeof(buf), "%s/share/elementary", s);
+             _elm_data_dir = eina_stringshare_add(buf);
+          }
+     }
+   if (!_elm_lib_dir)
+     {
+        s = getenv("ELM_LIB_DIR");
+        _elm_lib_dir = eina_stringshare_add(s);
+     }
+   if (!_elm_lib_dir)
+     {
+        s = getenv("ELM_PREFIX");
+        if (s)
+          {
+             snprintf(buf, sizeof(buf), "%s/lib", s);
+             _elm_lib_dir = eina_stringshare_add(buf);
+          }
+     }
+#ifdef HAVE_DLADDR
+   if ((!_elm_data_dir) || (!_elm_lib_dir))
+     {
+        Dl_info elementary_dl;
+        // libelementary.so/../../share/elementary/
+        if (dladdr(elm_init, &elementary_dl))
+          {
+             char *dir, *dir2;
+
+             dir = ecore_file_dir_get(elementary_dl.dli_fname);
+             if (dir)
+               {
+                  if (!_elm_lib_dir)
+                    {
+                       if (ecore_file_is_dir(dir))
+                         _elm_lib_dir = eina_stringshare_add(dir);
+                    }
+                  if (!_elm_data_dir)
+                    {
+                       dir2 = ecore_file_dir_get(dir);
+                       if (dir2)
+                         {
+                            snprintf(buf, sizeof(buf), "%s/share/elementary", dir2);
+                            if (ecore_file_is_dir(buf))
+                              _elm_data_dir = eina_stringshare_add(buf);
+                            free(dir2);
+                         }
+                    }
+                  free(dir);
+               }
+          }
+     }
+#endif
+   if (!_elm_data_dir)
+     _elm_data_dir = eina_stringshare_add(PACKAGE_DATA_DIR);
+   if (!_elm_data_dir)
+     _elm_data_dir = eina_stringshare_add("/");
+   if (!_elm_lib_dir)
+     _elm_lib_dir = eina_stringshare_add(PACKAGE_LIB_DIR);
+   if (!_elm_lib_dir)
+     _elm_lib_dir = eina_stringshare_add("/");
+
+   _elm_config_init();
+   return _elm_ql_init_count;
+}
+
+EAPI int
+elm_quicklaunch_sub_init(int    argc,
+                         char **argv)
+{
+   _elm_sub_init_count++;
+   if (_elm_sub_init_count > 1) return _elm_sub_init_count;
+   if (quicklaunch_on)
+     {
+#ifdef SEMI_BROKEN_QUICKLAUNCH
+        return _elm_sub_init_count;
+#endif
+     }
+   if (!quicklaunch_on)
+     {
+        ecore_app_args_set(argc, (const char **)argv);
+        evas_init();
+        edje_init();
+        _elm_module_init();
+        _elm_config_sub_init();
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+        if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
+            ENGINE_COMPARE(ELM_XRENDER_X11) ||
+            ENGINE_COMPARE(ELM_OPENGL_X11))
+#undef ENGINE_COMPARE
+          {
+#ifdef HAVE_ELEMENTARY_X
+             ecore_x_init(NULL);
+#endif
+          }
+        ecore_evas_init(); // FIXME: check errors
+        ecore_imf_init();
+     }
+   return _elm_sub_init_count;
+}
+
+EAPI int
+elm_quicklaunch_sub_shutdown(void)
+{
+   _elm_sub_init_count--;
+   if (_elm_sub_init_count > 0) return _elm_sub_init_count;
+   if (quicklaunch_on)
+     {
+#ifdef SEMI_BROKEN_QUICKLAUNCH
+        return _elm_sub_init_count;
+#endif
+     }
+   if (!quicklaunch_on)
+     {
+        _elm_win_shutdown();
+        _elm_module_shutdown();
+        ecore_imf_shutdown();
+        ecore_evas_shutdown();
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+        if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
+            ENGINE_COMPARE(ELM_XRENDER_X11) ||
+            ENGINE_COMPARE(ELM_OPENGL_X11))
+#undef ENGINE_COMPARE
+          {
+#ifdef HAVE_ELEMENTARY_X
+             ecore_x_disconnect();
+#endif
+          }
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+        if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
+            ENGINE_COMPARE(ELM_XRENDER_X11) ||
+            ENGINE_COMPARE(ELM_OPENGL_X11) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_SDL) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_SDL) ||
+            ENGINE_COMPARE(ELM_OPENGL_SDL) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_WIN32) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
+#undef ENGINE_COMPARE
+          evas_cserve_disconnect();
+        edje_shutdown();
+        evas_shutdown();
+     }
+   return _elm_sub_init_count;
+}
+
+EAPI int
+elm_quicklaunch_shutdown(void)
+{
+   _elm_ql_init_count--;
+   if (_elm_ql_init_count > 0) return _elm_ql_init_count;
+   eina_stringshare_del(_elm_data_dir);
+   _elm_data_dir = NULL;
+   eina_stringshare_del(_elm_lib_dir);
+   _elm_lib_dir = NULL;
+
+   free(_elm_appname);
+   _elm_appname = NULL;
+
+   _elm_config_shutdown();
+
+   ecore_event_handler_del(_elm_exit_handler);
+   _elm_exit_handler = NULL;
+
+   _elm_theme_shutdown();
+   _elm_unneed_efreet();
+   _elm_unneed_e_dbus();
+   _elm_unneed_ethumb();
+   ecore_file_shutdown();
+   ecore_shutdown();
+   eet_shutdown();
+
+   if ((_elm_log_dom > -1) && (_elm_log_dom != EINA_LOG_DOMAIN_GLOBAL))
+     {
+        eina_log_domain_unregister(_elm_log_dom);
+        _elm_log_dom = -1;
+     }
+
+   _elm_widget_type_clear();
+
+   eina_shutdown();
+   return _elm_ql_init_count;
+}
+
+EAPI void
+elm_quicklaunch_seed(void)
+{
+#ifndef SEMI_BROKEN_QUICKLAUNCH
+   if (quicklaunch_on)
+     {
+        Evas_Object *win, *bg, *bt;
+
+        win = elm_win_add(NULL, "seed", ELM_WIN_BASIC);
+        bg = elm_bg_add(win);
+        elm_win_resize_object_add(win, bg);
+        evas_object_show(bg);
+        bt = elm_button_add(win);
+        elm_button_label_set(bt, " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~-_=+\\|]}[{;:'\",<.>/?");
+        elm_win_resize_object_add(win, bt);
+        ecore_main_loop_iterate();
+        evas_object_del(win);
+        ecore_main_loop_iterate();
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+        if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
+            ENGINE_COMPARE(ELM_XRENDER_X11) ||
+            ENGINE_COMPARE(ELM_OPENGL_X11))
+#undef ENGINE_COMPARE
+          {
+# ifdef HAVE_ELEMENTARY_X
+             ecore_x_sync();
+# endif
+          }
+        ecore_main_loop_iterate();
+     }
+#endif
+}
+
+static void *qr_handle = NULL;
+static int (*qr_main)(int    argc,
+                      char **argv) = NULL;
+
+EAPI Eina_Bool
+elm_quicklaunch_prepare(int argc __UNUSED__,
+                        char   **argv)
+{
+#ifdef HAVE_FORK
+   char *exe = elm_quicklaunch_exe_path_get(argv[0]);
+   if (!exe)
+     {
+        ERR("requested quicklaunch binary '%s' does not exist\n", argv[0]);
+        return EINA_FALSE;
+     }
+   else
+     {
+        char *exe2, *p;
+        char *exename;
+
+        exe2 = malloc(strlen(exe) + 1 + 10);
+        strcpy(exe2, exe);
+        p = strrchr(exe2, '/');
+        if (p) p++;
+        else p = exe2;
+        exename = alloca(strlen(p) + 1);
+        strcpy(exename, p);
+        *p = 0;
+        strcat(p, "../lib/");
+        strcat(p, exename);
+        strcat(p, ".so");
+        if (!access(exe2, R_OK | X_OK))
+          {
+             free(exe);
+             exe = exe2;
+          }
+        else
+          free(exe2);
+     }
+   qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL);
+   if (!qr_handle)
+     {
+        fprintf(stderr, "dlerr: %s\n", dlerror());
+        WRN("dlopen('%s') failed: %s", exe, dlerror());
+        free(exe);
+        return EINA_FALSE;
+     }
+   INF("dlopen('%s') = %p", exe, qr_handle);
+   qr_main = dlsym(qr_handle, "elm_main");
+   INF("dlsym(%p, 'elm_main') = %p", qr_handle, qr_main);
+   if (!qr_main)
+     {
+        WRN("not quicklauncher capable: no elm_main in '%s'", exe);
+        dlclose(qr_handle);
+        qr_handle = NULL;
+        free(exe);
+        return EINA_FALSE;
+     }
+   free(exe);
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+   (void)argv;
+#endif
+}
+
+#ifdef HAVE_FORK
+static void
+save_env(void)
+{
+   int i, size;
+   extern char **environ;
+   char **oldenv, **p;
+
+   oldenv = environ;
+
+   for (i = 0, size = 0; environ[i]; i++)
+     size += strlen(environ[i]) + 1;
+
+   p = malloc((i + 1) * sizeof(char *));
+   if (!p) return;
+
+   environ = p;
+
+   for (i = 0; oldenv[i]; i++)
+     environ[i] = strdup(oldenv[i]);
+   environ[i] = NULL;
+}
+
+#endif
+
+EAPI Eina_Bool
+elm_quicklaunch_fork(int    argc,
+                     char **argv,
+                     char  *cwd,
+                     void (postfork_func) (void *data),
+                     void  *postfork_data)
+{
+#ifdef HAVE_FORK
+   pid_t child;
+   int ret;
+   int real_argc;
+   char **real_argv;
+
+   // FIXME:
+   // need to accept current environment from elementary_run
+   if (!qr_main)
+     {
+        int i;
+        char **args;
+
+        child = fork();
+        if (child > 0) return EINA_TRUE;
+        else if (child < 0)
+          {
+             perror("could not fork");
+             return EINA_FALSE;
+          }
+        setsid();
+        if (chdir(cwd) != 0)
+          perror("could not chdir");
+        args = alloca((argc + 1) * sizeof(char *));
+        for (i = 0; i < argc; i++) args[i] = argv[i];
+        args[argc] = NULL;
+        WRN("%s not quicklaunch capable, fallback...", argv[0]);
+        execvp(argv[0], args);
+        ERR("failed to execute '%s': %s", argv[0], strerror(errno));
+        exit(-1);
+     }
+   child = fork();
+   if (child > 0) return EINA_TRUE;
+   else if (child < 0)
+     {
+        perror("could not fork");
+        return EINA_FALSE;
+     }
+   if (postfork_func) postfork_func(postfork_data);
+
+   if (quicklaunch_on)
+     {
+#ifdef SEMI_BROKEN_QUICKLAUNCH
+        ecore_app_args_set(argc, (const char **)argv);
+        evas_init();
+        edje_init();
+        _elm_config_sub_init();
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+        if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
+            ENGINE_COMPARE(ELM_XRENDER_X11) ||
+            ENGINE_COMPARE(ELM_OPENGL_X11))
+#undef ENGINE_COMPARE
+          {
+# ifdef HAVE_ELEMENTARY_X
+             ecore_x_init(NULL);
+# endif
+          }
+        ecore_evas_init(); // FIXME: check errors
+        ecore_imf_init();
+        _elm_module_init();
+#endif
+     }
+
+   setsid();
+   if (chdir(cwd) != 0)
+     perror("could not chdir");
+   // FIXME: this is very linux specific. it changes argv[0] of the process
+   // so ps etc. report what you'd expect. for other unixes and os's this
+   // may just not work
+   save_env();
+   if (argv)
+     {
+        char *lastarg, *p;
+
+        ecore_app_args_get(&real_argc, &real_argv);
+        lastarg = real_argv[real_argc - 1] + strlen(real_argv[real_argc - 1]);
+        for (p = real_argv[0]; p < lastarg; p++) *p = 0;
+        strcpy(real_argv[0], argv[0]);
+     }
+   ecore_app_args_set(argc, (const char **)argv);
+   ret = qr_main(argc, argv);
+   exit(ret);
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+   (void)argc;
+   (void)argv;
+   (void)cwd;
+   (void)postfork_func;
+   (void)postfork_data;
+#endif
+}
+
+EAPI void
+elm_quicklaunch_cleanup(void)
+{
+#ifdef HAVE_FORK
+   if (qr_handle)
+     {
+        dlclose(qr_handle);
+        qr_handle = NULL;
+        qr_main = NULL;
+     }
+#endif
+}
+
+EAPI int
+elm_quicklaunch_fallback(int    argc,
+                         char **argv)
+{
+   int ret;
+   elm_quicklaunch_init(argc, argv);
+   elm_quicklaunch_sub_init(argc, argv);
+   elm_quicklaunch_prepare(argc, argv);
+   ret = qr_main(argc, argv);
+   exit(ret);
+   return ret;
+}
+
+EAPI char *
+elm_quicklaunch_exe_path_get(const char *exe)
+{
+   static char *path = NULL;
+   static Eina_List *pathlist = NULL;
+   const char *pathitr;
+   const Eina_List *l;
+   char buf[PATH_MAX];
+   if (exe[0] == '/') return strdup(exe);
+   if ((exe[0] == '.') && (exe[1] == '/')) return strdup(exe);
+   if ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/')) return strdup(exe);
+   if (!path)
+     {
+        const char *p, *pp;
+        char *buf2;
+        path = getenv("PATH");
+        buf2 = alloca(strlen(path) + 1);
+        p = path;
+        pp = p;
+        for (;; )
+          {
+             if ((*p == ':') || (!*p))
+               {
+                  int len;
+
+                  len = p - pp;
+                  strncpy(buf2, pp, len);
+                  buf2[len] = 0;
+                  pathlist = eina_list_append(pathlist, eina_stringshare_add(buf2));
+                  if (!*p) break;
+                  p++;
+                  pp = p;
+               }
+             else
+               {
+                  if (!*p) break;
+                  p++;
+               }
+          }
+     }
+   EINA_LIST_FOREACH(pathlist, l, pathitr)
+     {
+        snprintf(buf, sizeof(buf), "%s/%s", pathitr, exe);
+        if (!access(buf, R_OK | X_OK)) return strdup(buf);
+     }
+   return NULL;
+}
+
+/**
+ * Run the main loop
+ *
+ * This call should be called just after all initialization is complete. This
+ * function will not return until elm_exit() is called. It will keep looping
+ * running the main event/processing loop for Elementary.
+ * @ingroup General
+ */
+EAPI void
+elm_run(void)
+{
+   ecore_main_loop_begin();
+}
+
+/**
+ * Exit the main loop
+ *
+ * If this call is called, it will flag the main loop to cease processing and
+ * return back to its parent function.
+ * @ingroup General
+ */
+EAPI void
+elm_exit(void)
+{
+   ecore_main_loop_quit();
+}
+
+/**
+ * Set new policy value.
+ *
+ * This will emit the ecore event ELM_EVENT_POLICY_CHANGED in the main
+ * loop giving the event information Elm_Event_Policy_Changed with
+ * policy identifier, new and old values.
+ *
+ * @param policy policy identifier as in Elm_Policy.
+ * @param value policy value, depends on identifiers, usually there is
+ *        an enumeration with the same prefix as the policy name, for
+ *        example: ELM_POLICY_QUIT and Elm_Policy_Quit
+ *        (ELM_POLICY_QUIT_NONE, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED).
+ * @ingroup General
+ *
+ * @return @c EINA_TRUE on success or @c EINA_FALSE on error (right
+ *         now just invalid policy identifier, but in future policy
+ *         value might be enforced).
+ */
+EAPI Eina_Bool
+elm_policy_set(unsigned int policy,
+               int          value)
+{
+   Elm_Event_Policy_Changed *ev;
+
+   if (policy >= ELM_POLICY_LAST)
+     return EINA_FALSE;
+
+   if (value == _elm_policies[policy])
+     return EINA_TRUE;
+
+   /* TODO: validade policy? */
+
+   ev = malloc(sizeof(*ev));
+   ev->policy = policy;
+   ev->new_value = value;
+   ev->old_value = _elm_policies[policy];
+
+   _elm_policies[policy] = value;
+
+   ecore_event_add(ELM_EVENT_POLICY_CHANGED, ev, NULL, NULL);
+
+   return EINA_TRUE;
+}
+
+/**
+ * Gets the policy value set for given identifier.
+ *
+ * @param policy policy identifier as in Elm_Policy.
+ * @ingroup General
+ *
+ * @return policy value. Will be 0 if policy identifier is invalid.
+ */
+EAPI int
+elm_policy_get(unsigned int policy)
+{
+   if (policy >= ELM_POLICY_LAST)
+     return 0;
+   return _elm_policies[policy];
+}
+
+/**
+ * @defgroup Scaling Selective Widget Scaling
+ *
+ * Different widgets can be scaled independently. These functions allow you to
+ * manipulate this scaling on a per-widget basis. The object and all its
+ * children get their scaling factors multiplied by the scale factor set.
+ * This is multiplicative, in that if a child also has a scale size set it is
+ * in turn multiplied by its parent's scale size. 1.0 means “don't scale”,
+ * 2.0 is double size, 0.5 is half etc.
+ */
+
+/**
+ * Set the scaling factor
+ *
+ * @param obj The object
+ * @param scale Scale factor (from 0.0 up, with 1.0 == no scaling)
+ * @ingroup Scaling
+ */
+EAPI void
+elm_object_scale_set(Evas_Object *obj,
+                     double       scale)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_scale_set(obj, scale);
+}
+
+/**
+ * Get the scaling factor
+ *
+ * @param obj The object
+ * @return The scaling factor set by elm_object_scale_set()
+ * @ingroup Scaling
+ */
+EAPI double
+elm_object_scale_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0.0);
+   return elm_widget_scale_get(obj);
+}
+
+/**
+ * Get the global scaling factor
+ *
+ * This gets the globally configured scaling factor that is applied to all
+ * objects.
+ *
+ * @return The scaling factor
+ * @ingroup Scaling
+ */
+EAPI double
+elm_scale_get(void)
+{
+   return _elm_config->scale;
+}
+
+/**
+ * Set the global scaling factor
+ *
+ * This sets the globally configured scaling factor that is applied to all
+ * objects.
+ *
+ * @param scale The scaling factor to set
+ * @ingroup Scaling
+ */
+EAPI void
+elm_scale_set(double scale)
+{
+   if (_elm_config->scale == scale) return;
+   _elm_config->scale = scale;
+   _elm_rescale();
+}
+
+/**
+ * Set the global scaling factor for all applications on the display
+ *
+ * This sets the globally configured scaling factor that is applied to all
+ * objects for all applications.
+ * @param scale The scaling factor to set
+ * @ingroup Scaling
+ */
+EAPI void
+elm_scale_all_set(double scale)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int scale_i = (unsigned int)(scale * 1000.0);
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_SCALE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &scale_i, 1);
+#endif
+}
+
+/**
+ * @defgroup Styles Styles
+ *
+ * Widgets can have different styles of look. These generic API's set
+ * styles of widgets, if they support them (and if the theme(s) do).
+ */
+
+/**
+ * Set the style
+ *
+ * This sets the name of the style
+ * @param obj The object
+ * @param style The style name to use
+ * @ingroup Styles
+ */
+EAPI void
+elm_object_style_set(Evas_Object *obj,
+                     const char  *style)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_style_set(obj, style);
+}
+
+/**
+ * Get the style
+ *
+ * This gets the style being used for that widget. Note that the string
+ * pointer is only valid as longas the object is valid and the style doesn't
+ * change.
+ *
+ * @param obj The object
+ * @return The style name
+ * @ingroup Styles
+ */
+EAPI const char *
+elm_object_style_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   return elm_widget_style_get(obj);
+}
+
+/**
+ * Set the disable state
+ *
+ * This sets the disable state for the widget.
+ *
+ * @param obj The object
+ * @param disabled The state
+ * @ingroup Styles
+ */
+EAPI void
+elm_object_disabled_set(Evas_Object *obj,
+                        Eina_Bool    disabled)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_disabled_set(obj, disabled);
+}
+
+/**
+ * Get the disable state
+ *
+ * This gets the disable state for the widget.
+ *
+ * @param obj The object
+ * @return True, if the widget is disabled
+ * @ingroup Styles
+ */
+EAPI Eina_Bool
+elm_object_disabled_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
+   return elm_widget_disabled_get(obj);
+}
+
+/**
+ * @defgroup Config Elementary Config
+ *
+ * Elementary configuration is formed by a set options bounded to a
+ * given @ref Profile profile, like @ref Theme theme, @ref Fingers
+ * "finger size", etc. These are functions with which one syncronizes
+ * changes made to those values to the configuration storing files, de
+ * facto. You most probably don't want to use the functions in this
+ * group unlees you're writing an elementary configuration manager.
+ */
+
+/**
+ * Save back Elementary's configuration, so that it will persist on
+ * future sessions.
+ *
+ * @return @c EINA_TRUE, when sucessful. @c EINA_FALSE, otherwise.
+ * @ingroup Config
+ *
+ * This function will take effect -- thus, do I/O -- immediately. Use
+ * it when you want to apply all configuration changes at once. The
+ * current configuration set will get saved onto the current profile
+ * configuration file.
+ *
+ */
+EAPI Eina_Bool
+elm_config_save(void)
+{
+   return _elm_config_save();
+}
+
+/**
+ * Reload Elementary's configuration, bounded to current selected
+ * profile.
+ *
+ * @return @c EINA_TRUE, when sucessful. @c EINA_FALSE, otherwise.
+ * @ingroup Config
+ *
+ * Useful when you want to force reloading of configuration values for
+ * a profile. If one removes user custom configuration directories,
+ * for example, it will force a reload with system values insted.
+ *
+ */
+EAPI void
+elm_config_reload(void)
+{
+   _elm_config_reload();
+}
+
+/**
+ * @defgroup Profile Elementary Profile
+ *
+ * Profiles are pre-set options that affect the whole look-and-feel of
+ * Elementary-based applications. There are, for example, profiles
+ * aimed at desktop computer applications and others aimed at mobile,
+ * touchscreen-based ones. You most probably don't want to use the
+ * functions in this group unlees you're writing an elementary
+ * configuration manager.
+ */
+
+/**
+ * Get Elementary's profile in use.
+ *
+ * This gets the global profile that is applied to all Elementary
+ * applications.
+ *
+ * @return The profile's name
+ * @ingroup Profile
+ */
+EAPI const char *
+elm_profile_current_get(void)
+{
+   return _elm_config_current_profile_get();
+}
+
+/**
+ * Get an Elementary's profile directory path in the filesystem. One
+ * may want to fetch a system profile's dir or an user one (fetched
+ * inside $HOME).
+ *
+ * @param profile The profile's name
+ * @param is_user Whether to lookup for an user profile (@c EINA_TRUE)
+ *                or a system one (@c EINA_FALSE)
+ * @return The profile's directory path.
+ * @ingroup Profile
+ *
+ * @note You must free it with elm_profile_dir_free().
+ */
+EAPI const char *
+elm_profile_dir_get(const char *profile,
+                    Eina_Bool   is_user)
+{
+   return _elm_config_profile_dir_get(profile, is_user);
+}
+
+/**
+ * Free an Elementary's profile directory path, as returned by
+ * elm_profile_dir_get().
+ *
+ * @param p_dir The profile's path
+ * @ingroup Profile
+ *
+ */
+EAPI void
+elm_profile_dir_free(const char *p_dir)
+{
+   free((void *)p_dir);
+}
+
+/**
+ * Get Elementary's list of available profiles.
+ *
+ * @return The profiles list. List node data are the profile name
+ *         strings.
+ * @ingroup Profile
+ *
+ * @note One must free this list, after usage, with the function
+ *       elm_profile_list_free().
+ */
+EAPI Eina_List *
+elm_profile_list_get(void)
+{
+   return _elm_config_profiles_list();
+}
+
+/**
+ * Free Elementary's list of available profiles.
+ *
+ * @param The profiles list, as returned by elm_profile_list_get().
+ * @ingroup Profile
+ *
+ */
+EAPI void
+elm_profile_list_free(Eina_List *l)
+{
+   const char *dir;
+
+   EINA_LIST_FREE(l, dir)
+     eina_stringshare_del(dir);
+}
+
+/**
+ * Set Elementary's profile.
+ *
+ * This sets the global profile that is applied to Elementary
+ * applications. Just the process the call comes from will be
+ * affected.
+ *
+ * @param profile The profile's name
+ * @ingroup Profile
+ *
+ */
+EAPI void
+elm_profile_set(const char *profile)
+{
+   EINA_SAFETY_ON_NULL_RETURN(profile);
+   _elm_config_profile_set(profile);
+}
+
+/**
+ * Set Elementary's profile.
+ *
+ * This sets the global profile that is applied to all Elementary
+ * applications. All running Elementary windows will be affected.
+ *
+ * @param profile The profile's name
+ * @ingroup Profile
+ *
+ */
+EAPI void
+elm_profile_all_set(const char *profile)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_PROFILE");
+   ecore_x_window_prop_string_set(ecore_x_window_root_first_get(),
+                                  atom, profile);
+#endif
+}
+
+/**
+ * @defgroup Engine Elementary Engine
+ *
+ * These are functions setting and querying which rendering engine
+ * Elementary will use for drawing its windows' pixels.
+ */
+
+/**
+ * Get Elementary's rendering engine in use.
+ *
+ * This gets the global rendering engine that is applied to all
+ * Elementary applications.
+ *
+ * @return The rendering engine's name
+ * @ingroup Engine
+ *
+ * @note there's no need to free the returned string, here.
+ */
+EAPI const char *
+elm_engine_current_get(void)
+{
+   return _elm_config->engine;
+}
+
+/**
+ * Set Elementary's rendering engine for use.
+ *
+ * This gets sets global rendering engine that is applied to all
+ * Elementary applications. Note that it will take effect only to
+ * subsequent Elementary window creations.
+ *
+ * @param The rendering engine's name
+ * @ingroup Engine
+ *
+ * @note there's no need to free the returned string, here.
+ */
+EAPI void
+elm_engine_set(const char *engine)
+{
+   EINA_SAFETY_ON_NULL_RETURN(engine);
+
+   _elm_config_engine_set(engine);
+}
+
+/**
+ * @defgroup Fonts Elementary Fonts
+ *
+ * These are functions dealing with font rendering, selection and the
+ * like for Elementary applications. One might fetch which system
+ * fonts are there to use and set custom fonts for individual classes
+ * of UI items containing text (text classes).
+ */
+
+/**
+ * Get Elementary's list of supported text classes.
+ *
+ * @return The text classes list, with @c Elm_Text_Class blobs as data.
+ * @ingroup Fonts
+ *
+ * Release the list with elm_text_classes_list_free().
+ */
+EAPI const Eina_List *
+elm_text_classes_list_get(void)
+{
+   return _elm_config_text_classes_get();
+}
+
+/**
+ * Free Elementary's list of supported text classes.
+ *
+ * @ingroup Fonts
+ *
+ * @see elm_text_classes_list_get().
+ */
+EAPI void
+elm_text_classes_list_free(const Eina_List *list)
+{
+   _elm_config_text_classes_free((Eina_List *)list);
+}
+
+/**
+ * Get Elementary's list of font overlays, set with
+ * elm_font_overlay_set().
+ *
+ * @return The font overlays list, with @c Elm_Font_Overlay blobs as
+ * data.
+ *
+ * @ingroup Fonts
+ *
+ * For each text class, one can set a <b>font overlay</b> for it,
+ * overriding the default font properties for that class coming from
+ * the theme in use. There is no need to free this list.
+ *
+ * @see elm_font_overlay_set() and elm_font_overlay_unset().
+ */
+EAPI const Eina_List *
+elm_font_overlay_list_get(void)
+{
+   return _elm_config_font_overlays_list();
+}
+
+/**
+ * Set a font overlay for a given Elementary text class.
+ *
+ * @param text_class Text class name
+ * @param font Font name and style string
+ * @param size Font size
+ *
+ * @ingroup Fonts
+ *
+ * @p font has to be in the format returned by
+ * elm_font_fontconfig_name_get(). @see elm_font_overlay_list_get()
+ * and @elm_font_overlay_unset().
+ */
+EAPI void
+elm_font_overlay_set(const char    *text_class,
+                     const char    *font,
+                     Evas_Font_Size size)
+{
+   _elm_config_font_overlay_set(text_class, font, size);
+}
+
+/**
+ * Unset a font overlay for a given Elementary text class.
+ *
+ * @param text_class Text class name
+ *
+ * @ingroup Fonts
+ *
+ * This will bring back text elements belonging to text class @p
+ * text_class back to their default font settings.
+ */
+EAPI void
+elm_font_overlay_unset(const char *text_class)
+{
+   _elm_config_font_overlay_remove(text_class);
+}
+
+/**
+ * Apply the changes made with elm_font_overlay_set() and
+ * elm_font_overlay_unset() on the current Elementary window.
+ *
+ * @ingroup Fonts
+ *
+ * This applies all font overlays set to all objects in the UI.
+ */
+EAPI void
+elm_font_overlay_apply(void)
+{
+   _elm_config_font_overlay_apply();
+}
+
+/**
+ * Apply the changes made with elm_font_overlay_set() and
+ * elm_font_overlay_unset() on all Elementary application windows.
+ *
+ * @ingroup Fonts
+ *
+ * This applies all font overlays set to all objects in the UI.
+ */
+EAPI void
+elm_font_overlay_all_apply(void)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int dummy = (unsigned int)(1 * 1000.0);
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_FONT_OVERLAY");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(), atom, &dummy,
+                                  1);
+#endif
+}
+
+/**
+ * Translate a font (family) name string in fontconfig's font names
+ * syntax into an @c Elm_Font_Properties struct.
+ *
+ * @param font The font name and styles string
+ * @return the font properties struct
+ *
+ * @ingroup Fonts
+ *
+ * @note The reverse translation can be achived with
+ * elm_font_fontconfig_name_get(), for one style only (single font
+ * instance, not family).
+ */
+EAPI Elm_Font_Properties *
+elm_font_properties_get(const char *font)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(font, NULL);
+   return _elm_font_properties_get(NULL, font);
+}
+
+/**
+ * Free font properties return by elm_font_properties_get().
+ *
+ * @param efp the font properties struct
+ *
+ * @ingroup Fonts
+ */
+EAPI void
+elm_font_properties_free(Elm_Font_Properties *efp)
+{
+   const char *str;
+
+   EINA_SAFETY_ON_NULL_RETURN(efp);
+   EINA_LIST_FREE(efp->styles, str)
+     if (str) eina_stringshare_del(str);
+   if (efp->name) eina_stringshare_del(efp->name);
+   free(efp);
+}
+
+/**
+ * Translate a font name, bound to a style, into fontconfig's font names
+ * syntax.
+ *
+ * @param name The font (family) name
+ * @param style The given style (may be @c NULL)
+ *
+ * @return the font name and style string
+ *
+ * @ingroup Fonts
+ *
+ * @note The reverse translation can be achived with
+ * elm_font_properties_get(), for one style only (single font
+ * instance, not family).
+ */
+EAPI const char *
+elm_font_fontconfig_name_get(const char *name,
+                             const char *style)
+{
+   char buf[256];
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+   if (!style || style[0] == 0) return eina_stringshare_add(name);
+   snprintf(buf, 256, "%s" ELM_FONT_TOKEN_STYLE "%s", name, style);
+   return eina_stringshare_add(buf);
+}
+
+/**
+ * Free the font string return by elm_font_fontconfig_name_get().
+ *
+ * @param efp the font properties struct
+ *
+ * @ingroup Fonts
+ */
+EAPI void
+elm_font_fontconfig_name_free(const char *name)
+{
+   eina_stringshare_del(name);
+}
+
+/**
+ * Create a font hash table of available system fonts.
+ *
+ * One must call it with @p list being the return value of
+ * evas_font_available_list(). The hash will be indexed by font
+ * (family) names, being its values @c Elm_Font_Properties blobs.
+ *
+ * @param list The list of available system fonts, as returned by
+ * evas_font_available_list().
+ * @return the font hash.
+ *
+ * @ingroup Fonts
+ *
+ * @note The user is supposed to get it populated at least with 3
+ * default font families (Sans, Serif, Monospace), which should be
+ * present on most systems.
+ */
+EAPI Eina_Hash *
+elm_font_available_hash_add(Eina_List *list)
+{
+   Eina_Hash *font_hash;
+   Eina_List *l;
+   void *key;
+
+   font_hash = NULL;
+
+   /* populate with default font families */
+   font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Regular");
+   font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Bold");
+   font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Oblique");
+   font_hash = _elm_font_available_hash_add(font_hash,
+                                            "Sans:style=Bold Oblique");
+
+   font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Regular");
+   font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Bold");
+   font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Oblique");
+   font_hash = _elm_font_available_hash_add(font_hash,
+                                            "Serif:style=Bold Oblique");
+
+   font_hash = _elm_font_available_hash_add(font_hash,
+                                            "Monospace:style=Regular");
+   font_hash = _elm_font_available_hash_add(font_hash,
+                                            "Monospace:style=Bold");
+   font_hash = _elm_font_available_hash_add(font_hash,
+                                            "Monospace:style=Oblique");
+   font_hash = _elm_font_available_hash_add(font_hash,
+                                            "Monospace:style=Bold Oblique");
+
+   EINA_LIST_FOREACH(list, l, key)
+     font_hash = _elm_font_available_hash_add(font_hash, key);
+
+   return font_hash;
+}
+
+/**
+ * Free the hash return by elm_font_available_hash_add().
+ *
+ * @param hash the hash to be freed.
+ *
+ * @ingroup Fonts
+ */
+EAPI void
+elm_font_available_hash_del(Eina_Hash *hash)
+{
+   _elm_font_available_hash_del(hash);
+}
+
+/**
+ * @defgroup Fingers Fingers
+ *
+ * Elementary is designed to be finger-friendly for touchscreens, and so in
+ * addition to scaling for display resolution, it can also scale based on
+ * finger "resolution" (or size).
+ */
+
+/**
+ * Get the configured finger size
+ *
+ * This gets the globally configured finger size in pixels
+ *
+ * @return The finger size
+ * @ingroup Fingers
+ */
+EAPI Evas_Coord
+elm_finger_size_get(void)
+{
+   return _elm_config->finger_size;
+}
+
+/**
+ * Set the configured finger size
+ *
+ * This sets the globally configured finger size in pixels
+ *
+ * @param size The finger size
+ * @ingroup Fingers
+ */
+EAPI void
+elm_finger_size_set(Evas_Coord size)
+{
+   if (_elm_config->finger_size == size) return;
+   _elm_config->finger_size = size;
+   _elm_rescale();
+}
+
+/**
+ * Set the configured finger size for all applications on the display
+ *
+ * This sets the globally configured finger size in pixels for all applications
+ * on the display
+ *
+ * @param size The finger size
+ * @ingroup Fingers
+ */
+EAPI void
+elm_finger_size_all_set(Evas_Coord size)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int size_i = (unsigned int)size;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_FINGER_SIZE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &size_i, 1);
+#endif
+}
+
+/**
+ * Adjust size of an element for finger usage
+ *
+ * This takes width and height sizes (in pixels) as input and a size multiple
+ * (which is how many fingers you want to place within the area), and adjusts
+ * the size tobe large enough to accommodate finger. On return the w and h
+ * sizes poiner do by these parameters will be modified.
+ *
+ * @param times_w How many fingers should fit horizontally
+ * @param w Pointer to the width size to adjust
+ * @param times_h How many fingers should fit vertically
+ * @param h Pointer to the height size to adjust
+ * @ingroup Fingers
+ */
+EAPI void
+elm_coords_finger_size_adjust(int         times_w,
+                              Evas_Coord *w,
+                              int         times_h,
+                              Evas_Coord *h)
+{
+   if ((w) && (*w < (_elm_config->finger_size * times_w)))
+     *w = _elm_config->finger_size * times_w;
+   if ((h) && (*h < (_elm_config->finger_size * times_h)))
+     *h = _elm_config->finger_size * times_h;
+}
+
+/**
+ * @defgroup Caches Caches
+ *
+ * These are functions which let one fine-tune some cache values for
+ * Elementary applications, thus allowing for performance adjustments.
+ */
+
+/**
+ * Flush all caches & dump all data that can be to lean down to use
+ * less memory
+ *
+ * @ingroup Caches
+ */
+EAPI void
+elm_all_flush(void)
+{
+   const Eina_List *l;
+   Evas_Object *obj;
+
+   EINA_LIST_FOREACH(_elm_win_list, l, obj)
+     {
+        Evas *e = evas_object_evas_get(obj);
+        edje_file_cache_flush();
+        edje_collection_cache_flush();
+        eet_clearcache();
+        evas_image_cache_flush(e);
+        evas_font_cache_flush(e);
+        evas_render_dump(e);
+     }
+}
+
+/**
+ * Get the configured cache flush interval time
+ *
+ * This gets the globally configured cache flush interval time, in
+ * ticks
+ *
+ * @return The cache flush interval time
+ * @ingroup Caches
+ *
+ * @see elm_all_flush()
+ */
+EAPI int
+elm_cache_flush_interval_get(void)
+{
+   return _elm_config->cache_flush_poll_interval;
+}
+
+/**
+ * Set the configured cache flush interval time
+ *
+ * This sets the globally configured cache flush interval time, in ticks
+ *
+ * @param size The cache flush interval time
+ * @ingroup Caches
+ *
+ * @see elm_all_flush()
+ */
+EAPI void
+elm_cache_flush_interval_set(int size)
+{
+   if (_elm_config->cache_flush_poll_interval == size) return;
+   _elm_config->cache_flush_poll_interval = size;
+
+   _elm_recache();
+}
+
+/**
+ * Set the configured cache flush interval time for all applications on the
+ * display
+ *
+ * This sets the globally configured cache flush interval time -- in ticks
+ * -- for all applications on the display.
+ *
+ * @param size The cache flush interval time
+ * @ingroup Caches
+ */
+EAPI void
+elm_cache_flush_interval_all_set(int size)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int size_i = (unsigned int)size;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_CACHE_FLUSH_INTERVAL");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &size_i, 1);
+#endif
+}
+
+/**
+ * Get the configured cache flush enabled state
+ *
+ * This gets the globally configured cache flush state - if it is enabled
+ * or not. When cache flushing is enabled, elementary will regularly
+ * (see elm_cache_flush_interval_get() ) flush caches and dump data out of
+ * memory and allow usage to re-seed caches and data in memory where it
+ * can do so. An idle application will thus minimise its memory usage as
+ * data will be freed from memory and not be re-loaded as it is idle and
+ * not rendering or doing anything graphically right now.
+ *
+ * @return The cache flush state
+ * @ingroup Caches
+ *
+ * @see elm_all_flush()
+ */
+EAPI Eina_Bool
+elm_cache_flush_enmabled_get(void)
+{
+   return _elm_config->cache_flush_enable;
+}
+
+/**
+ * Set the configured cache flush enabled state
+ *
+ * This sets the globally configured cache flush enabled state
+ *
+ * @param size The cache flush enabled state
+ * @ingroup Caches
+ *
+ * @see elm_all_flush()
+ */
+EAPI void
+elm_cache_flush_enabled_set(Eina_Bool enabled)
+{
+   enabled = !!enabled;
+   if (_elm_config->cache_flush_enable == enabled) return;
+   _elm_config->cache_flush_enable = enabled;
+
+   _elm_recache();
+}
+
+/**
+ * Set the configured cache flush enabled state for all applications on the
+ * display
+ *
+ * This sets the globally configured cache flush enabled state for all 
+ * applications on the display.
+ *
+ * @param size The cache flush enabled state
+ * @ingroup Caches
+ */
+EAPI void
+elm_cache_flush_enabled_all_set(Eina_Bool enabled)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int enabled_i = (unsigned int)enabled;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_CACHE_FLUSH_ENABLE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &enabled_i, 1);
+#endif
+}
+
+/**
+ * Get the configured font cache size
+ *
+ * This gets the globally configured font cache size, in bytes
+ *
+ * @return The font cache size
+ * @ingroup Caches
+ */
+EAPI int
+elm_font_cache_get(void)
+{
+   return _elm_config->font_cache;
+}
+
+/**
+ * Set the configured font cache size
+ *
+ * This sets the globally configured font cache size, in bytes
+ *
+ * @param size The font cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_font_cache_set(int size)
+{
+   if (_elm_config->font_cache == size) return;
+   _elm_config->font_cache = size;
+
+   _elm_recache();
+}
+
+/**
+ * Set the configured font cache size for all applications on the
+ * display
+ *
+ * This sets the globally configured font cache size -- in bytes
+ * -- for all applications on the display.
+ *
+ * @param size The font cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_font_cache_all_set(int size)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int size_i = (unsigned int)size;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_FONT_CACHE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &size_i, 1);
+#endif
+}
+
+/**
+ * Get the configured image cache size
+ *
+ * This gets the globally configured image cache size, in bytes
+ *
+ * @return The image cache size
+ * @ingroup Caches
+ */
+EAPI int
+elm_image_cache_get(void)
+{
+   return _elm_config->image_cache;
+}
+
+/**
+ * Set the configured image cache size
+ *
+ * This sets the globally configured image cache size, in bytes
+ *
+ * @param size The image cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_image_cache_set(int size)
+{
+   if (_elm_config->image_cache == size) return;
+   _elm_config->image_cache = size;
+
+   _elm_recache();
+}
+
+/**
+ * Set the configured image cache size for all applications on the
+ * display
+ *
+ * This sets the globally configured image cache size -- in bytes
+ * -- for all applications on the display.
+ *
+ * @param size The image cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_image_cache_all_set(int size)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int size_i = (unsigned int)size;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_IMAGE_CACHE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &size_i, 1);
+#endif
+}
+
+/**
+ * Get the configured edje file cache size.
+ *
+ * This gets the globally configured edje file cache size, in number
+ * of files.
+ *
+ * @return The edje file cache size
+ * @ingroup Caches
+ */
+EAPI int
+elm_edje_file_cache_get(void)
+{
+   return _elm_config->edje_cache;
+}
+
+/**
+ * Set the configured edje file cache size
+ *
+ * This sets the globally configured edje file cache size, in number
+ * of files.
+ *
+ * @param size The edje file cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_edje_file_cache_set(int size)
+{
+   if (_elm_config->edje_cache == size) return;
+   _elm_config->edje_cache = size;
+
+   _elm_recache();
+}
+
+/**
+ * Set the configured edje file cache size for all applications on the
+ * display
+ *
+ * This sets the globally configured edje file cache size -- in number
+ * of files -- for all applications on the display.
+ *
+ * @param size The edje file cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_edje_file_cache_all_set(int size)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int size_i = (unsigned int)size;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_EDJE_FILE_CACHE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &size_i, 1);
+#endif
+}
+
+/**
+ * Get the configured edje collections (groups) cache size.
+ *
+ * This gets the globally configured edje collections cache size, in
+ * number of collections.
+ *
+ * @return The edje collections cache size
+ * @ingroup Caches
+ */
+EAPI int
+elm_edje_collection_cache_get(void)
+{
+   return _elm_config->edje_collection_cache;
+}
+
+/**
+ * Set the configured edje collections (groups) cache size
+ *
+ * This sets the globally configured edje collections cache size, in
+ * number of collections.
+ *
+ * @param size The edje collections cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_edje_collection_cache_set(int size)
+{
+   if (_elm_config->edje_collection_cache == size) return;
+   _elm_config->edje_collection_cache = size;
+
+   _elm_recache();
+}
+
+/**
+ * Set the configured edje collections (groups) cache size for all
+ * applications on the display
+ *
+ * This sets the globally configured edje collections cache size -- in
+ * number of collections -- for all applications on the display.
+ *
+ * @param size The edje collections cache size
+ * @ingroup Caches
+ */
+EAPI void
+elm_edje_collection_cache_all_set(int size)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int size_i = (unsigned int)size;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_EDJE_COLLECTION_CACHE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &size_i, 1);
+#endif
+}
+
+/**
+ * @defgroup Focus Focus
+ *
+ * Objects have focus. This is what determines where the keyboard input goes to
+ * within the application window.
+ */
+
+/**
+ * Get the focus of the object
+ *
+ * This gets the focused property of the object.
+ *
+ * @param obj The object
+ * @return 1 if the object is focused, 0 if not.
+ * @ingroup Focus
+ */
+EAPI Eina_Bool
+elm_object_focus_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
+   return elm_widget_focus_get(obj);
+}
+
+/**
+ * Set the focus to the object
+ *
+ * This sets the focus target for keyboard input to be the object indicated.
+ *
+ * @param obj The object
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus(Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   if (elm_widget_focus_get(obj))
+     return;
+
+   elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
+}
+
+/**
+ * Remove the focus from the object
+ *
+ * This removes the focus target for keyboard input from be the object
+ * indicated.
+ *
+ * @param obj The object
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_unfocus(Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   if (!elm_widget_can_focus_get(obj)) return;
+   elm_widget_focused_object_clear(obj);
+}
+
+/**
+ * Set the ability for the object to focus
+ *
+ * This sets the ability for the object to be able to get keyboard focus or
+ * not. By default all objects are able to be focused.
+ *
+ * @param obj The object
+ * @param enable 1 if the object can be focused, 0 if not
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus_allow_set(Evas_Object *obj,
+                           Eina_Bool    enable)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_can_focus_set(obj, enable);
+}
+
+/**
+ * Get the ability for the object to focus
+ *
+ * This gets the ability for the object to be able to get keyboard focus or
+ * not. By default all objects are able to be focused.
+ *
+ * @param obj The object
+ * @return 1 if the object is allowed to be focused, 0 if not.
+ * @ingroup Focus
+ */
+EAPI Eina_Bool
+elm_object_focus_allow_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
+   return (elm_widget_can_focus_get(obj)) || (elm_widget_child_can_focus_get(obj));
+}
+
+/**
+ * Set custom focus chain.
+ *
+ * This function i set one new and overwrite any previous custom focus chain
+ * with the list of objects. The previous list will be deleted and this list
+ * will be managed. After setted, don't modity it.
+ *
+ * @note On focus cycle, only will be evaluated children of this container.
+ *
+ * @param obj The container object
+ * @param objs Chain of objects to pass focus
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus_custom_chain_set(Evas_Object *obj,
+                                  Eina_List   *objs)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_focus_custom_chain_set(obj, objs);
+}
+
+/**
+ * Unset custom focus chain
+ *
+ * @param obj The container object
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus_custom_chain_unset(Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_focus_custom_chain_unset(obj);
+}
+
+/**
+ * Get custom focus chain
+ *
+ * @param obj The container object
+ * @ingroup Focus
+ */
+EAPI const Eina_List *
+elm_object_focus_custom_chain_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   return elm_widget_focus_custom_chain_get(obj);
+}
+
+/**
+ * Append object to custom focus chain.
+ *
+ * @note If relative_child equal to NULL or not in custom chain, the object
+ * will be added in end.
+ *
+ * @note On focus cycle, only will be evaluated children of this container.
+ *
+ * @param obj The container object
+ * @param child The child to be added in custom chain
+ * @param relative_child The relative object to position the child
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus_custom_chain_append(Evas_Object *obj,
+                                     Evas_Object *child,
+                                     Evas_Object *relative_child)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   EINA_SAFETY_ON_NULL_RETURN(child);
+   elm_widget_focus_custom_chain_append(obj, child, relative_child);
+}
+
+/**
+ * Prepend object to custom focus chain.
+ *
+ * @note If relative_child equal to NULL or not in custom chain, the object
+ * will be added in begin.
+ *
+ * @note On focus cycle, only will be evaluated children of this container.
+ *
+ * @param obj The container object
+ * @param child The child to be added in custom chain
+ * @param relative_child The relative object to position the child
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus_custom_chain_prepend(Evas_Object *obj,
+                                      Evas_Object *child,
+                                      Evas_Object *relative_child)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   EINA_SAFETY_ON_NULL_RETURN(child);
+   elm_widget_focus_custom_chain_prepend(obj, child, relative_child);
+}
+
+/**
+ * Give focus to next object in object tree.
+ *
+ * Give focus to next object in focus chain of one object sub-tree.
+ * If the last object of chain already have focus, the focus will go to the
+ * first object of chain.
+ *
+ * @param obj The object root of sub-tree
+ * @param dir Direction to cycle the focus
+ *
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus_cycle(Evas_Object        *obj,
+                       Elm_Focus_Direction dir)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_focus_cycle(obj, dir);
+}
+
+/**
+ * Give focus to near object in one direction.
+ *
+ * Give focus to near object in direction of one object.
+ * If none focusable object in given direction, the focus will not change.
+ *
+ * @param obj The reference object
+ * @param x Horizontal component of direction to focus
+ * @param y Vertical component of direction to focus
+ *
+ * @ingroup Focus
+ */
+EAPI void
+elm_object_focus_direction_go(Evas_Object *obj,
+                              int          x,
+                              int          y)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_focus_direction_go(obj, x, y);
+}
+
+/**
+ * Get the enable status of the focus highlight
+ *
+ * This gets whether the highlight on focused objects is enabled or not
+ * @ingroup Focus
+ */
+EAPI Eina_Bool
+elm_focus_highlight_enabled_get(void)
+{
+   return _elm_config->focus_highlight_enable;
+}
+
+/**
+ * Set the enable status of the focus highlight
+ *
+ * Set whether to show or not the highlight on focused objects
+ * @param enable Enable highlight if EINA_TRUE, disable otherwise
+ * @ingroup Focus
+ */
+EAPI void
+elm_focus_highlight_enabled_set(Eina_Bool enable)
+{
+   _elm_config->focus_highlight_enable = !!enable;
+}
+
+/**
+ * Get the enable status of the highlight animation
+ *
+ * Get whether the focus highlight, if enabled, will animate its switch from
+ * one object to the next
+ * @ingroup Focus
+ */
+EAPI Eina_Bool
+elm_focus_highlight_animate_get(void)
+{
+   return _elm_config->focus_highlight_animate;
+}
+
+/**
+ * Set the enable status of the highlight animation
+ *
+ * Set whether the focus highlight, if enabled, will animate its switch from
+ * one object to the next
+ * @param animate Enable animation if EINA_TRUE, disable otherwise
+ * @ingroup Focus
+ */
+EAPI void
+elm_focus_highlight_animate_set(Eina_Bool animate)
+{
+   _elm_config->focus_highlight_animate = !!animate;
+}
+
+/**
+ * @defgroup Scrolling Scrolling
+ *
+ * These are functions setting how scrollable views in Elementary
+ * widgets should behave on user interaction.
+ */
+
+/**
+ * Get whether scrollers should bounce when they reach their
+ * viewport's edge during a scroll.
+ *
+ * @return the thumb scroll bouncing state
+ *
+ * This is the default behavior for touch screens, in general.
+ * @ingroup Scrolling
+ */
+EAPI Eina_Bool
+elm_scroll_bounce_enabled_get(void)
+{
+   return _elm_config->thumbscroll_bounce_enable;
+}
+
+/**
+ * Set whether scrollers should bounce when they reach their
+ * viewport's edge during a scroll.
+ *
+ * @param enabled the thumb scroll bouncing state
+ *
+ * @see elm_thumbscroll_bounce_enabled_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_bounce_enabled_set(Eina_Bool enabled)
+{
+   _elm_config->thumbscroll_bounce_enable = enabled;
+}
+
+/**
+ * Set whether scrollers should bounce when they reach their
+ * viewport's edge during a scroll, for all Elementary application
+ * windows.
+ *
+ * @param enabled the thumb scroll bouncing state
+ *
+ * @see elm_thumbscroll_bounce_enabled_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_bounce_enabled_all_set(Eina_Bool enabled)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int bounce_enable_i = (unsigned int)enabled;
+
+   if (!atom)
+     atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_BOUNCE_ENABLE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &bounce_enable_i, 1);
+#endif
+}
+
+/**
+ * Get the amount of inertia a scroller will impose at bounce
+ * animations.
+ *
+ * @return the thumb scroll bounce friction
+ *
+ * @ingroup Scrolling
+ */
+EAPI double
+elm_scroll_bounce_friction_get(void)
+{
+   return _elm_config->thumbscroll_bounce_friction;
+}
+
+/**
+ * Set the amount of inertia a scroller will impose at bounce
+ * animations.
+ *
+ * @param friction the thumb scroll bounce friction
+ *
+ * @see elm_thumbscroll_bounce_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_bounce_friction_set(double friction)
+{
+   _elm_config->thumbscroll_bounce_friction = friction;
+}
+
+/**
+ * Set the amount of inertia a scroller will impose at bounce
+ * animations, for all Elementary application windows.
+ *
+ * @param friction the thumb scroll bounce friction
+ *
+ * @see elm_thumbscroll_bounce_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_bounce_friction_all_set(double friction)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int bounce_friction_i = (unsigned int)(friction * 1000.0);
+
+   if (!atom)
+     atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_BOUNCE_FRICTION");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &bounce_friction_i, 1);
+#endif
+}
+
+/**
+ * Get the amount of inertia a <b>paged</b> scroller will impose at
+ * page fitting animations.
+ *
+ * @return the page scroll friction
+ *
+ * @ingroup Scrolling
+ */
+EAPI double
+elm_scroll_page_scroll_friction_get(void)
+{
+   return _elm_config->page_scroll_friction;
+}
+
+/**
+ * Set the amount of inertia a <b>paged</b> scroller will impose at
+ * page fitting animations.
+ *
+ * @param friction the page scroll friction
+ *
+ * @see elm_thumbscroll_page_scroll_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_page_scroll_friction_set(double friction)
+{
+   _elm_config->page_scroll_friction = friction;
+}
+
+/**
+ * Set the amount of inertia a <b>paged</b> scroller will impose at
+ * page fitting animations, for all Elementary application windows.
+ *
+ * @param friction the page scroll friction
+ *
+ * @see elm_thumbscroll_page_scroll_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_page_scroll_friction_all_set(double friction)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int page_scroll_friction_i = (unsigned int)(friction * 1000.0);
+
+   if (!atom)
+     atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_PAGE_SCROLL_FRICTION");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &page_scroll_friction_i, 1);
+#endif
+}
+
+/**
+ * Get the amount of inertia a scroller will impose at region bring
+ * animations.
+ *
+ * @return the bring in scroll friction
+ *
+ * @ingroup Scrolling
+ */
+EAPI double
+elm_scroll_bring_in_scroll_friction_get(void)
+{
+   return _elm_config->bring_in_scroll_friction;
+}
+
+/**
+ * Set the amount of inertia a scroller will impose at region bring
+ * animations.
+ *
+ * @param friction the bring in scroll friction
+ *
+ * @see elm_thumbscroll_bring_in_scroll_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_bring_in_scroll_friction_set(double friction)
+{
+   _elm_config->bring_in_scroll_friction = friction;
+}
+
+/**
+ * Set the amount of inertia a scroller will impose at region bring
+ * animations, for all Elementary application windows.
+ *
+ * @param friction the bring in scroll friction
+ *
+ * @see elm_thumbscroll_bring_in_scroll_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_bring_in_scroll_friction_all_set(double friction)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int bring_in_scroll_friction_i = (unsigned int)(friction * 1000.0);
+
+   if (!atom)
+     atom =
+       ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_BRING_IN_SCROLL_FRICTION");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &bring_in_scroll_friction_i, 1);
+#endif
+}
+
+/**
+ * Get the amount of inertia scrollers will impose at animations
+ * triggered by Elementary widgets' zooming API.
+ *
+ * @return the zoom friction
+ *
+ * @ingroup Scrolling
+ */
+EAPI double
+elm_scroll_zoom_friction_get(void)
+{
+   return _elm_config->zoom_friction;
+}
+
+/**
+ * Set the amount of inertia scrollers will impose at animations
+ * triggered by Elementary widgets' zooming API.
+ *
+ * @param friction the zoom friction
+ *
+ * @see elm_thumbscroll_zoom_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_zoom_friction_set(double friction)
+{
+   _elm_config->zoom_friction = friction;
+}
+
+/**
+ * Set the amount of inertia scrollers will impose at animations
+ * triggered by Elementary widgets' zooming API, for all Elementary
+ * application windows.
+ *
+ * @param friction the zoom friction
+ *
+ * @see elm_thumbscroll_zoom_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_zoom_friction_all_set(double friction)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int zoom_friction_i = (unsigned int)(friction * 1000.0);
+
+   if (!atom)
+     atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_ZOOM_FRICTION");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &zoom_friction_i, 1);
+#endif
+}
+
+/**
+ * Get whether scrollers should be draggable from any point in their
+ * views.
+ *
+ * @return the thumb scroll state
+ *
+ * @note This is the default behavior for touch screens, in general.
+ * @note All other functions namespaced with "thumbscroll" will only
+ *       have effect if this mode is enabled.
+ *
+ * @ingroup Scrolling
+ */
+EAPI Eina_Bool
+elm_scroll_thumbscroll_enabled_get(void)
+{
+   return _elm_config->thumbscroll_enable;
+}
+
+/**
+ * Set whether scrollers should be draggable from any point in their
+ * views.
+ *
+ * @param enabled the thumb scroll state
+ *
+ * @see elm_thumbscroll_enabled_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_enabled_set(Eina_Bool enabled)
+{
+   _elm_config->thumbscroll_enable = enabled;
+}
+
+/**
+ * Set whether scrollers should be draggable from any point in their
+ * views, for all Elementary application windows.
+ *
+ * @param enabled the thumb scroll state
+ *
+ * @see elm_thumbscroll_enabled_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_enabled_all_set(Eina_Bool enabled)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int ts_enable_i = (unsigned int)enabled;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_ENABLE");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &ts_enable_i, 1);
+#endif
+}
+
+/**
+ * Get the number of pixels one should travel while dragging a
+ * scroller's view to actually trigger scrolling.
+ *
+ * @return the thumb scroll threshould
+ *
+ * One would use higher values for touch screens, in general, because
+ * of their inherent imprecision.
+ * @ingroup Scrolling
+ */
+EAPI unsigned int
+elm_scroll_thumbscroll_threshold_get(void)
+{
+   return _elm_config->thumbscroll_threshold;
+}
+
+/**
+ * Set the number of pixels one should travel while dragging a
+ * scroller's view to actually trigger scrolling.
+ *
+ * @param threshold the thumb scroll threshould
+ *
+ * @see elm_thumbscroll_threshould_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_threshold_set(unsigned int threshold)
+{
+   _elm_config->thumbscroll_threshold = threshold;
+}
+
+/**
+ * Set the number of pixels one should travel while dragging a
+ * scroller's view to actually trigger scrolling, for all Elementary
+ * application windows.
+ *
+ * @param threshold the thumb scroll threshould
+ *
+ * @see elm_thumbscroll_threshould_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_threshold_all_set(unsigned int threshold)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int ts_threshold_i = (unsigned int)threshold;
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_THRESHOLD");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &ts_threshold_i, 1);
+#endif
+}
+
+/**
+ * Get the minimum speed of mouse cursor movement which will trigger
+ * list self scrolling animation after a mouse up event
+ * (pixels/second).
+ *
+ * @return the thumb scroll momentum threshould
+ *
+ * @ingroup Scrolling
+ */
+EAPI double
+elm_scroll_thumbscroll_momentum_threshold_get(void)
+{
+   return _elm_config->thumbscroll_momentum_threshold;
+}
+
+/**
+ * Set the minimum speed of mouse cursor movement which will trigger
+ * list self scrolling animation after a mouse up event
+ * (pixels/second).
+ *
+ * @param threshold the thumb scroll momentum threshould
+ *
+ * @see elm_thumbscroll_momentum_threshould_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_momentum_threshold_set(double threshold)
+{
+   _elm_config->thumbscroll_momentum_threshold = threshold;
+}
+
+/**
+ * Set the minimum speed of mouse cursor movement which will trigger
+ * list self scrolling animation after a mouse up event
+ * (pixels/second), for all Elementary application windows.
+ *
+ * @param threshold the thumb scroll momentum threshould
+ *
+ * @see elm_thumbscroll_momentum_threshould_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_momentum_threshold_all_set(double threshold)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int ts_momentum_threshold_i = (unsigned int)(threshold * 1000.0);
+
+   if (!atom)
+     atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_MOMENTUM_THRESHOLD");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &ts_momentum_threshold_i, 1);
+#endif
+}
+
+/**
+ * Get the amount of inertia a scroller will impose at self scrolling
+ * animations.
+ *
+ * @return the thumb scroll friction
+ *
+ * @ingroup Scrolling
+ */
+EAPI double
+elm_scroll_thumbscroll_friction_get(void)
+{
+   return _elm_config->thumbscroll_friction;
+}
+
+/**
+ * Set the amount of inertia a scroller will impose at self scrolling
+ * animations.
+ *
+ * @param friction the thumb scroll friction
+ *
+ * @see elm_thumbscroll_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_friction_set(double friction)
+{
+   _elm_config->thumbscroll_friction = friction;
+}
+
+/**
+ * Set the amount of inertia a scroller will impose at self scrolling
+ * animations, for all Elementary application windows.
+ *
+ * @param friction the thumb scroll friction
+ *
+ * @see elm_thumbscroll_friction_get()
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_friction_all_set(double friction)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int ts_friction_i = (unsigned int)(friction * 1000.0);
+
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_FRICTION");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &ts_friction_i, 1);
+#endif
+}
+
+/**
+ * Get the amount of lag between your actual mouse cursor dragging
+ * movement and a scroller's view movement itself, while pushing it
+ * into bounce state manually.
+ *
+ * @return the thumb scroll border friction
+ *
+ * @ingroup Scrolling
+ */
+EAPI double
+elm_scroll_thumbscroll_border_friction_get(void)
+{
+   return _elm_config->thumbscroll_border_friction;
+}
+
+/**
+ * Set the amount of lag between your actual mouse cursor dragging
+ * movement and a scroller's view movement itself, while pushing it
+ * into bounce state manually.
+ *
+ * @param friction the thumb scroll border friction. @c 0.0 for
+ *        perfect synchrony between two movements, @c 1.0 for maximum
+ *        lag.
+ *
+ * @see elm_thumbscroll_border_friction_get()
+ * @note parameter value will get bound to 0.0 - 1.0 interval, always
+ *
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_border_friction_set(double friction)
+{
+   if (friction < 0.0)
+     friction = 0.0;
+
+   if (friction > 1.0)
+     friction = 1.0;
+
+   _elm_config->thumbscroll_friction = friction;
+}
+
+/**
+ * Set the amount of lag between your actual mouse cursor dragging
+ * movement and a scroller's view movement itself, while pushing it
+ * into bounce state manually, for all Elementary application windows.
+ *
+ * @param friction the thumb scroll border friction. @c 0.0 for
+ *        perfect synchrony between two movements, @c 1.0 for maximum
+ *        lag.
+ *
+ * @see elm_thumbscroll_border_friction_get()
+ * @note parameter value will get bound to 0.0 - 1.0 interval, always
+ *
+ * @ingroup Scrolling
+ */
+EAPI void
+elm_scroll_thumbscroll_border_friction_all_set(double friction)
+{
+   if (friction < 0.0)
+     friction = 0.0;
+
+   if (friction > 1.0)
+     friction = 1.0;
+
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   unsigned int border_friction_i = (unsigned int)(friction * 1000.0);
+
+   if (!atom)
+     atom = ecore_x_atom_get("ENLIGHTENMENT_THUMBSCROLL_BORDER_FRICTION");
+   ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
+                                  atom, &border_friction_i, 1);
+#endif
+}
+
+/**
+ * @defgroup Scrollhints Scrollhints
+ *
+ * Objects when inside a scroller can scroll, but this may not always be
+ * desirable in certain situations. This allows an object to hint to itself
+ * and parents to "not scroll" in one of 2 ways.
+ *
+ * 1. To hold on scrolling. This means just flicking and dragging may no
+ * longer scroll, but pressing/dragging near an edge of the scroller will
+ * still scroll. This is automastically used by the entry object when
+ * selecting text.
+ * 2. To totally freeze scrolling. This means it stops. until popped/released.
+ */
+
+/**
+ * Push the scroll hold by 1
+ *
+ * This increments the scroll hold count by one. If it is more than 0 it will
+ * take effect on the parents of the indicated object.
+ *
+ * @param obj The object
+ * @ingroup Scrollhints
+ */
+EAPI void
+elm_object_scroll_hold_push(Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_scroll_hold_push(obj);
+}
+
+/**
+ * Pop the scroll hold by 1
+ *
+ * This decrements the scroll hold count by one. If it is more than 0 it will
+ * take effect on the parents of the indicated object.
+ *
+ * @param obj The object
+ * @ingroup Scrollhints
+ */
+EAPI void
+elm_object_scroll_hold_pop(Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_scroll_hold_pop(obj);
+}
+
+/**
+ * Push the scroll freeze by 1
+ *
+ * This increments the scroll freeze count by one. If it is more than 0 it will
+ * take effect on the parents of the indicated object.
+ *
+ * @param obj The object
+ * @ingroup Scrollhints
+ */
+EAPI void
+elm_object_scroll_freeze_push(Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_scroll_freeze_push(obj);
+}
+
+/**
+ * Lock the scrolling of the given widget (and thus all parents)
+ *
+ * This locks the given object from scrolling in the X axis (and implicitly
+ * also locks all parent scrollers too from doing the same).
+ *
+ * @param obj The object
+ * @param lock The lock state (1 == locked, 0 == unlocked)
+ * @ingroup Scrollhints
+ */
+EAPI void
+elm_object_scroll_lock_x_set(Evas_Object *obj,
+                             Eina_Bool    lock)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_drag_lock_x_set(obj, lock);
+}
+
+/**
+ * Lock the scrolling of the given widget (and thus all parents)
+ *
+ * This locks the given object from scrolling in the Y axis (and implicitly
+ * also locks all parent scrollers too from doing the same).
+ *
+ * @param obj The object
+ * @param lock The lock state (1 == locked, 0 == unlocked)
+ * @ingroup Scrollhints
+ */
+EAPI void
+elm_object_scroll_lock_y_set(Evas_Object *obj,
+                             Eina_Bool    lock)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_drag_lock_y_set(obj, lock);
+}
+
+/**
+ * Get the scrolling lock of the given widget
+ *
+ * This gets the lock for X axis scrolling.
+ *
+ * @param obj The object
+ * @ingroup Scrollhints
+ */
+EAPI Eina_Bool
+elm_object_scroll_lock_x_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
+   return elm_widget_drag_lock_x_get(obj);
+}
+
+/**
+ * Get the scrolling lock of the given widget
+ *
+ * This gets the lock for X axis scrolling.
+ *
+ * @param obj The object
+ * @ingroup Scrollhints
+ */
+EAPI Eina_Bool
+elm_object_scroll_lock_y_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
+   return elm_widget_drag_lock_y_get(obj);
+}
+
+/**
+ * Pop the scroll freeze by 1
+ *
+ * This decrements the scroll freeze count by one. If it is more than 0 it will
+ * take effect on the parents of the indicated object.
+ *
+ * @param obj The object
+ * @ingroup Scrollhints
+ */
+EAPI void
+elm_object_scroll_freeze_pop(Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_scroll_freeze_pop(obj);
+}
+
+/**
+ * @defgroup WidgetNavigation Widget Tree Navigation.
+ *
+ * How to check if an Evas Object is an Elementary widget? How to get
+ * the first elementary widget that is parent of the given object?
+ * These are all covered in widget tree navigation.
+ */
+
+/**
+ * Check if the given Evas Object is an Elementary widget.
+ *
+ * @param obj the object to query.
+ * @return @c EINA_TRUE if it is an elementary widget variant,
+ *         @c EINA_FALSE otherwise
+ * @ingroup WidgetNavigation
+ */
+EAPI Eina_Bool
+elm_object_widget_check(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
+   return elm_widget_is(obj);
+}
+
+/**
+ * Get the first parent of the given object that is an Elementary widget.
+ *
+ * @param obj the object to query.
+ * @return the parent object that is an Elementary widget, or @c NULL
+ *         if no parent is, or no parents at all.
+ * @ingroup WidgetNavigation
+ */
+EAPI Evas_Object *
+elm_object_parent_widget_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   return elm_widget_parent_widget_get(obj);
+}
+
+/**
+ * Get the top level parent of an Elementary widget.
+ *
+ * @param obj The object to query.
+ * @return The top level Elementary widget, or @c NULL if parent cannot be
+ * found.
+ * @ingroup WidgetNavigation
+ */
+EAPI Evas_Object *
+elm_object_top_widget_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   return elm_widget_top_get(obj);
+}
+
+/**
+ * Get the string that represents this Elementary widget.
+ *
+ * @note Elementary is weird and exposes itself as a single
+ *       Evas_Object_Smart_Class of type "elm_widget", so
+ *       evas_object_type_get() always return that, making debug and
+ *       language bindings hard. This function tries to mitigate this
+ *       problem, but the solution is to change Elementary to use
+ *       proper inheritance.
+ *
+ * @param obj the object to query.
+ * @return Elementary widget name, or @c NULL if not a valid widget.
+ * @ingroup WidgetNavigation
+ */
+EAPI const char *
+elm_object_widget_type_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   return elm_widget_type_get(obj);
+}
+
+/**
+ * Send a signal to the widget edje object.
+ *
+ * This function sends a signal to the edje object of the obj. An edje program
+ * can respond to a signal by specifying matching 'signal' and
+ * 'source' fields.
+ *
+ * @param obj The object
+ * @param emission The signal's name.
+ * @param source The signal's source.
+ * @ingroup General
+ */
+EAPI void
+elm_object_signal_emit(Evas_Object *obj,
+                       const char  *emission,
+                       const char  *source)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_signal_emit(obj, emission, source);
+}
+
+/**
+ * Add a callback for a signal emitted by widget edje object.
+ *
+ * This function connects a callback function to a signal emitted by the
+ * edje object of the obj.
+ * Globs can occur in either the emission or source name.
+ *
+ * @param obj The object
+ * @param emission The signal's name.
+ * @param source The signal's source.
+ * @param func The callback function to be executed when the signal is
+ * emitted.
+ * @param data A pointer to data to pass in to the callback function.
+ * @ingroup General
+ */
+EAPI void 
+elm_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+    EINA_SAFETY_ON_NULL_RETURN(obj);
+    EINA_SAFETY_ON_NULL_RETURN(func);
+    elm_widget_signal_callback_add(obj, emission, source, func, data);
+}
+
+/**
+ * Remove a signal-triggered callback from an widget edje object.
+ *
+ * This function removes a callback, previoulsy attached to a signal emitted
+ * by the edje object of the obj.
+ * The parameters emission, source and func must match exactly those passed to
+ * a previous call to elm_object_signal_callback_add(). The data pointer that
+ * was passed to this call will be returned.
+ *
+ * @param obj The object
+ * @param emission The signal's name.
+ * @param source The signal's source.
+ * @param func The callback function to be executed when the signal is
+ * emitted.
+ * @return The data pointer
+ * @ingroup General
+ */
+EAPI void *
+elm_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source))
+{
+    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
+    return elm_widget_signal_callback_del(obj, emission, source, func);
+}
+
+/**
+ * Add a callback for a event emitted by widget or their children.
+ *
+ * This function connects a callback function to any key_down key_up event
+ * emitted by the @p obj or their children.
+ * This only will be called if no other callback has consumed the event.
+ * If you want consume the event, and no other get it, func should return
+ * EINA_TRUE and put EVAS_EVENT_FLAG_ON_HOLD in event_flags.
+ *
+ * @warning Accept duplicated callback addition.
+ *
+ * @param obj The object
+ * @param func The callback function to be executed when the event is
+ * emitted.
+ * @param data Data to pass in to the callback function.
+ * @ingroup General
+ */
+EAPI void
+elm_object_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   elm_widget_event_callback_add(obj, func, data);
+}
+
+/**
+ * Remove a event callback from an widget.
+ *
+ * This function removes a callback, previoulsy attached to event emission
+ * by the @p obj.
+ * The parameters func and data must match exactly those passed to
+ * a previous call to elm_object_event_callback_add(). The data pointer that
+ * was passed to this call will be returned.
+ *
+ * @param obj The object
+ * @param func The callback function to be executed when the event is
+ * emitted.
+ * @param data Data to pass in to the callback function.
+ * @return The data pointer
+ * @ingroup General
+ */
+EAPI void *
+elm_object_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
+   return elm_widget_event_callback_del(obj, func, data);
+}
+
+
+/**
+ * @defgroup Debug Debug
+ */
+
+/**
+ * Print Tree object hierarchy in stdout
+ *
+ * @param obj The root object
+ * @ingroup Debug
+ */
+EAPI void
+elm_object_tree_dump(const Evas_Object *top)
+{
+#ifdef ELM_DEBUG
+   elm_widget_tree_dump(top);
+#else
+   return;
+   (void)top;
+#endif
+}
+
+/**
+ * Print Elm Objects tree hierarchy in file as dot(graphviz) syntax.
+ *
+ * @param obj The root object
+ * @param file The path of output file
+ * @ingroup Debug
+ */
+EAPI void
+elm_object_tree_dot_dump(const Evas_Object *top,
+                         const char        *file)
+{
+#ifdef ELM_DEBUG
+   FILE *f = fopen(file, "w");
+   elm_widget_tree_dot_dump(top, f);
+   fclose(f);
+#else
+   return;
+   (void)top;
+   (void)file;
+#endif
+}
+
+/**
+ * Set the duration for occuring long press event.
+ *
+ * @param lonpress_timeout Timeout for long press event
+ * @ingroup Longpress
+ */
+EAPI void
+elm_longpress_timeout_set(double longpress_timeout)
+{
+   _elm_config->longpress_timeout = longpress_timeout;
+}
+
+/**
+ * Get the duration for occuring long press event.
+ *
+ * @return Timeout for long press event
+ * @ingroup Longpress
+ */
+EAPI double
+elm_longpress_timeout_get(void)
+{
+   return _elm_config->longpress_timeout;
+}
diff --git a/src/lib/elm_map.c b/src/lib/elm_map.c
new file mode 100644 (file)
index 0000000..11fadad
--- /dev/null
@@ -0,0 +1,3627 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Map Map
+ * @ingroup Elementary
+ *
+ * This is a widget specifically for displaying the free map OpenStreetMap.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * clicked - This is called when a user has clicked the map without dragging
+ * around.
+ *
+ * press - This is called when a user has pressed down on the map.
+ *
+ * longpressed - This is called when a user has pressed down on the map for
+ * a long time without dragging around.
+ *
+ * clicked,double - This is called when a user has double-clicked the photo.
+ *
+ * load,detail - Map detailed data load begins.
+ *
+ * loaded,detail - This is called when all parts of the map are loaded.
+ *
+ * zoom,start - Zoom animation started.
+ *
+ * zoom,stop - Zoom animation stopped.
+ *
+ * zoom,change - Zoom changed when using an auto zoom mode.
+ *
+ * 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
+ *
+ * downloaded - This is called when map images are downloaded
+ *
+ * TODO : doxygen
+ */
+
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Pan Pan;
+typedef struct _Grid Grid;
+typedef struct _Grid_Item Grid_Item;
+typedef struct _Marker_Group Marker_Group;
+typedef struct _Mod_Api Mod_Api;
+typedef struct _Event Event;
+
+#define DEST_DIR_ZOOM_PATH "/tmp/elm_map/%d/%d/"
+#define DEST_DIR_PATH DEST_DIR_ZOOM_PATH"%d/"
+#define DEST_FILE_PATH "%s%d.png"
+
+// Map sources
+// Currently the size of a tile must be 256*256
+// and the size of the map must be pow(2.0, z)*tile_size
+typedef struct _Map_Sources_Tab
+{
+   Elm_Map_Sources source;
+   const char *name;
+   int zoom_min;
+   int zoom_max;
+   ElmMapSourceURLFunc url_cb;
+} Map_Sources_Tab;
+
+#define ZOOM_MAX 18
+
+//Zemm min is supposed to be 0
+static char *_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char *_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char *_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char *_maplint_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char *_module_url_cb(Evas_Object *obj, int x, int y, int zoom);
+static char * _custom1_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char * _custom2_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char * _custom3_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char * _custom4_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char * _custom5_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+static char * _custom6_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
+
+static Map_Sources_Tab map_sources_tab[] =
+{
+     {ELM_MAP_SOURCE_MAPNIK, "Mapnik", 0, 18, _mapnik_url_cb},
+     {ELM_MAP_SOURCE_OSMARENDER, "Osmarender", 0, 17, _osmarender_url_cb},
+     {ELM_MAP_SOURCE_CYCLEMAP, "Cycle Map", 0, 17, _cyclemap_url_cb},
+     {ELM_MAP_SOURCE_MAPLINT, "Maplint", 12, 16, _maplint_url_cb},
+     {ELM_MAP_SOURCE_CUSTOM_1, "Custom 1", 0, 18, _custom1_url_cb},
+     {ELM_MAP_SOURCE_CUSTOM_2, "Custom 2", 0, 18, _custom2_url_cb},
+     {ELM_MAP_SOURCE_CUSTOM_3, "Custom 3", 0, 18, _custom3_url_cb},
+     {ELM_MAP_SOURCE_CUSTOM_4, "Custom 4", 0, 18, _custom4_url_cb},
+     {ELM_MAP_SOURCE_CUSTOM_5, "Custom 5", 0, 18, _custom5_url_cb},
+     {ELM_MAP_SOURCE_CUSTOM_6, "Custom 6", 0, 18, _custom6_url_cb},
+     {ELM_MAP_SOURCE_MODULE, "Module", 0, 18, _module_url_cb}
+};
+
+struct _Elm_Map_Marker_Class
+{
+   const char *style;
+   int zoom_displayed;
+
+   struct _Elm_Map_Marker_Class_Func {
+      ElmMapMarkerGetFunc get;
+      ElmMapMarkerDelFunc del; //if NULL the object will be destroyed with evas_object_del()
+      ElmMapMarkerIconGetFunc icon_get;
+   } func;
+
+   struct { //this part is private, do not modify these values
+      Eina_Bool set : 1;
+      Evas_Coord edje_w, edje_h;
+   } priv;
+};
+
+struct _Elm_Map_Marker
+{
+   Widget_Data *wd;
+   Elm_Map_Marker_Class *clas;
+   Elm_Map_Group_Class *clas_group;
+   double longitude, latitude;
+
+   Evas_Coord map_size;
+   Evas_Coord x[ZOOM_MAX+1], y[ZOOM_MAX+1];
+   void *data;
+
+   Marker_Group *groups[ZOOM_MAX+1];
+
+   Evas_Object *content;
+};
+
+struct _Elm_Map_Group_Class
+{
+   const char *style;
+   void *data;
+   int zoom_displayed; // display the group if the zoom is >= to zoom_display
+   int zoom_grouped; // group the markers only if the zoom is <= to zoom_groups
+   Eina_Bool hide : 1;
+
+   struct {
+      ElmMapGroupIconGetFunc icon_get;
+   } func;
+   
+   struct { //this part is private, do not modify these values
+      Eina_Bool set : 1;
+      Evas_Coord edje_w, edje_h;
+      Evas_Coord edje_max_w, edje_max_h;
+      
+      Eina_List *objs_used;
+      Eina_List *objs_notused;
+   } priv;
+};
+
+struct _Marker_Group
+{
+   Widget_Data *wd;
+   Eina_Matrixsparse_Cell *cell;
+   Elm_Map_Group_Class *clas;
+
+   Eina_List *markers;
+   long long sum_x, sum_y;
+   Evas_Coord x, y;
+   Evas_Coord w, h;
+
+   Evas_Object *obj, *bubble, *sc, *bx, *rect;
+   Eina_Bool open : 1;
+   Eina_Bool bringin : 1;
+   Eina_Bool update_nbelems : 1;
+   Eina_Bool update_resize : 1;
+   Eina_Bool update_raise : 1;
+   Eina_Bool delete_object : 1;
+};
+
+struct _Grid_Item
+{
+   Widget_Data *wd;
+   Evas_Object *img;
+   //Evas_Object *txt;
+   const char *file;
+   struct {
+      int x, y, w, h;
+   } src, out;
+   Eina_Bool want : 1;
+   Eina_Bool download : 1;
+   Eina_Bool have : 1;
+   Ecore_File_Download_Job *job;
+   int try_num;
+};
+
+struct _Grid
+{
+   Widget_Data *wd;
+   int tsize; // size of tile (tsize x tsize pixels)
+   int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8)
+   int iw, ih; // size of image in pixels
+   int w, h; // size of grid image in pixels (represented by grid)
+   int gw, gh; // size of grid in tiles
+   Eina_Matrixsparse *grid;
+};
+
+struct _Widget_Data
+{
+   Evas_Object *obj;
+   Evas_Object *scr;
+   Evas_Object *pan_smart;
+   Evas_Object *rect;
+   Evas_Object *sep_maps_markers; //map objects are below this object and marker objects are on top
+   Pan *pan;
+   Evas_Coord pan_x, pan_y, minw, minh;
+
+   int id;
+   int zoom;
+   Elm_Map_Zoom_Mode mode;
+
+   Ecore_Job *calc_job;
+   Ecore_Timer *scr_timer;
+   Ecore_Timer *long_timer;
+   Ecore_Animator *zoom_animator;
+   double t_start, t_end;
+   struct {
+      int w, h;
+      int ow, oh, nw, nh;
+      struct {
+         double x, y;
+      } spos;
+   } size;
+   struct {
+      Eina_Bool show : 1;
+      Evas_Coord x, y ,w ,h;
+   } show;
+   int tsize;
+   int nosmooth;
+   int preload_num;
+   Eina_List *grids;
+   Eina_Bool resized : 1;
+   Eina_Bool longpressed : 1;
+   Eina_Bool on_hold : 1;
+   Eina_Bool paused : 1;
+   Eina_Bool paused_markers : 1;
+   Eina_Bool pinch_zoom : 1;
+   
+   struct {
+      Eina_Bool enabled;
+      double lon, lat;
+   } center_on;
+
+   Ecore_Job *markers_place_job;
+   Eina_Matrixsparse *markers[ZOOM_MAX+1];
+   Eina_List *cells_displayed; // list of Eina_Matrixsparse_Cell
+   Evas_Coord markers_max_num;
+   int marker_max_w, marker_max_h;
+   int marker_zoom;
+   Eina_List *opened_bubbles; //opened bubbles, list of Map_Group *
+
+   Eina_List *groups_clas; // list of Elm_Map_Group_Class*
+   Eina_List *markers_clas; // list of Elm_Map_Markers_Class*
+
+   Elm_Map_Sources source;
+   Mod_Api *api;
+   Eina_List *s_event_list;
+   int try_num;
+   int finish_num;
+};
+
+struct _Mod_Api
+{
+   Eina_Bool (*obj_hook) (Evas_Object *obj);
+   Eina_Bool (*obj_unhook) (Evas_Object *obj);
+   char * (*obj_url_request) (Evas_Object *obj, int x, int y, int zoom);
+   Eina_Bool (*obj_convert_coord_into_geo) (const Evas_Object *obj, int zoom, int x, int y, int size, double *lon, double *lat);
+   Eina_Bool (*obj_convert_geo_into_coord) (const Evas_Object *obj, int zoom, double lon, double lat, int size, int *x, int *y);
+};
+struct _Pan
+{
+   Evas_Object_Smart_Clipped_Data __clipped_data;
+   Widget_Data *wd;
+};
+
+struct _Event
+{
+   int device;
+   
+   struct {
+      Evas_Coord x, y;
+   } prev;
+   
+   Evas_Coord x, y, w, h;
+   
+   Evas_Object *object;
+   Ecore_Timer *hold_timer;
+   
+   int pinch_dis;
+};
+
+static int dis_old = 0;
+static const char *widtype = NULL;
+
+static const char SIG_CHANGED[] = "changed";
+static const char SIG_CLICKED[] = "clicked";
+static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
+static const char SIG_LOADED_DETAIL[] = "loaded,detail";
+static const char SIG_LOAD_DETAIL[] = "load,detail";
+static const char SIG_LONGPRESSED[] = "longpressed";
+static const char SIG_PRESS[] = "press";
+static const char SIG_SCROLL[] = "scroll";
+static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
+static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
+static const char SIG_ZOOM_CHANGE[] = "zoom,change";
+static const char SIG_ZOOM_START[] = "zoom,start";
+static const char SIG_ZOOM_STOP[] = "zoom,stop";
+static const char SIG_DOWNLOADED[] = "downloaded";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CHANGED, ""},
+  {SIG_CLICKED, ""},
+  {SIG_CLICKED_DOUBLE, ""},
+  {SIG_LOADED_DETAIL, ""},
+  {SIG_LOAD_DETAIL, ""},
+  {SIG_LONGPRESSED, ""},
+  {SIG_PRESS, ""},
+  {SIG_SCROLL, ""},
+  {SIG_SCROLL_DRAG_START, ""},
+  {SIG_SCROLL_DRAG_STOP, ""},
+  {SIG_ZOOM_CHANGE, ""},
+  {SIG_ZOOM_START, ""},
+  {SIG_ZOOM_STOP, ""},
+  {SIG_DOWNLOADED, ""},
+  {NULL, NULL}
+};
+
+static void _pan_calculate(Evas_Object *obj);
+
+static Eina_Bool _hold_timer_cb(void *data);
+static void _rect_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _calc_job(void *data);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+static void grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
+static void grid_clear(Evas_Object *obj, Grid *g);
+static Grid *grid_create(Evas_Object *obj);
+static void grid_load(Evas_Object *obj, Grid *g);
+
+
+static void _group_object_create(Marker_Group *group);
+static void _group_object_free(Marker_Group *group);
+static void _group_open_cb(void *data, Evas_Object *obj, const char *emission, const char *soure);
+static void _group_bringin_cb(void *data, Evas_Object *obj, const char *emission, const char *soure);
+static void _group_bubble_create(Marker_Group *group);
+static void _group_bubble_free(Marker_Group *group);
+static void _group_bubble_place(Marker_Group *group);
+
+static int _group_bubble_content_update(Marker_Group *group);
+static void _group_bubble_content_free(Marker_Group *group);
+static void marker_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
+static void _bubble_sc_hits_changed_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+
+static void _mouse_multi_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+static void _mouse_multi_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+static void _mouse_multi_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
+
+static int
+get_multi_device(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Event *ev;
+   
+   EINA_LIST_FOREACH(wd->s_event_list, l, ev)
+     {
+        if (ev->device) return ev->device;                             
+     }
+   return 0;
+}
+
+static int
+get_distance(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2)
+{
+   int dx = x1 - x2;
+   int dy = y1 - y2;
+   return sqrt((dx * dx) + (dy * dy));
+}
+
+static Event *
+create_event_object(void *data, Evas_Object *obj, int device)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Event *ev = calloc(1, sizeof(Event));
+   
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
+   
+   ev->object = obj;
+   ev->device = device;
+   evas_object_geometry_get(obj, &ev->x, &ev->y, &ev->w, &ev->h);
+   wd->s_event_list = eina_list_append(wd->s_event_list, ev);
+   return ev;
+}
+
+static Event*
+get_event_object(void *data, int device)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Eina_List *l;
+   Event *ev;
+   
+   EINA_LIST_FOREACH(wd->s_event_list, l, ev)
+     {
+        if (ev->device == device) break;
+        ev = NULL;
+     }
+   return ev;
+}
+
+static void
+destroy_event_object(void *data, Event *ev)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   EINA_SAFETY_ON_NULL_RETURN(ev);
+   ev->pinch_dis = 0;
+   wd->s_event_list = eina_list_remove(wd->s_event_list, ev);
+   if (ev->hold_timer)
+     {
+        ecore_timer_del(ev->hold_timer);
+        ev->hold_timer = NULL;
+     }
+   free(ev);
+}
+
+static Mod_Api *
+module(Evas_Object *obj __UNUSED__)
+{
+   static Elm_Module *m = NULL;
+   if (m) goto ok;
+   if (!(m = _elm_module_find_as("map/api"))) return NULL;
+
+   m->api = malloc(sizeof(Mod_Api));
+   if (!m->api) return NULL;
+   ((Mod_Api *)(m->api)      )->obj_hook =
+     _elm_module_symbol_get(m, "obj_hook");
+   ((Mod_Api *)(m->api)      )->obj_unhook =
+     _elm_module_symbol_get(m, "obj_unhook");
+   ((Mod_Api *)(m->api)      )->obj_url_request =
+     _elm_module_symbol_get(m, "obj_url_request");
+   ((Mod_Api *)(m->api)      )->obj_convert_coord_into_geo =
+     _elm_module_symbol_get(m, "obj_convert_coord_into_geo");
+   ((Mod_Api *)(m->api)      )->obj_convert_geo_into_coord =
+     _elm_module_symbol_get(m, "obj_convert_geo_into_coord");
+   ok:
+   return m->api;
+}
+
+static void
+rect_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord ax, ay, gw, gh, hh, ww;
+   if (!wd) return;
+   evas_object_geometry_get(wd->rect, NULL, NULL, &ww, &hh);
+
+   ax = 0;
+   ay = 0;
+   gw = wd->size.w;
+   gh = wd->size.h;
+
+   if ((ww == gw) && (hh == gh)) return;
+
+   if (ow > gw) ax = (ow - gw) / 2;
+   if (oh > gh) ay = (oh - gh) / 2;
+   evas_object_move(wd->rect,
+                    ox + 0 - px + ax,
+                    oy + 0 - py + ay);
+   evas_object_resize(wd->rect, gw, gh);
+   
+   if (wd->show.show)
+     {
+       wd->show.show = EINA_FALSE;
+       elm_smart_scroller_child_region_show(wd->scr, wd->show.x, wd->show.y, wd->show.w, wd->show.h);
+     }
+}
+
+static void
+marker_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord ax, ay, gw, gh, tx, ty;
+   Eina_List *l, *markers;
+   Eina_Matrixsparse_Cell *cell;
+   Marker_Group *group;
+   int xx, yy, ww, hh;
+   char buf[PATH_MAX];
+   int y, x;
+   int g_xx, g_yy, g_hh, g_ww;
+
+   if (!wd) return;
+   if (g != eina_list_data_get(wd->grids)) return;
+
+   ax = 0;
+   ay = 0;
+   gw = wd->size.w;
+   gh = wd->size.h;
+   if (ow > gw) ax = (ow - gw) / 2;
+   if (oh > gh) ay = (oh - gh) / 2;
+
+   if (wd->zoom != wd->marker_zoom)
+     {
+       EINA_LIST_FREE(wd->cells_displayed, cell)
+         {
+            EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group)
+              {
+                 if (group->obj) _group_object_free(group);
+              }
+         }
+     }
+   wd->marker_zoom = wd->zoom;
+
+   if ((wd->paused_markers)
+       && ((wd->size.nw != wd->size.w) || (wd->size.nh != wd->size.h)) )
+     return;
+
+   g_xx = wd->pan_x / wd->tsize;
+   if (g_xx < 0) g_xx = 0;
+   g_yy = wd->pan_y / wd->tsize;
+   if (g_yy < 0) g_yy = 0;
+   g_ww =  ow / wd->tsize + 1;
+   if (g_xx + g_ww >= g->gw) g_ww = g->gw - g_xx - 1;
+   g_hh =  oh / wd->tsize + 1;
+   if (g_yy + g_hh >= g->gh) g_hh = g->gh - g_yy - 1;
+
+   //hide groups no more displayed
+   EINA_LIST_FREE(wd->cells_displayed, cell)
+     {
+       eina_matrixsparse_cell_position_get(cell, (unsigned long *)&y, (unsigned long *)&x);
+       if ((y < g_yy) || (y > g_yy + g_hh) || (x < g_xx) || (x > g_xx + g_ww))
+         {
+            EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group)
+              {
+                 if (group->obj) _group_object_free(group);
+              }
+         }
+     }
+
+   for (y = g_yy; y <= g_yy + g_hh; y++)
+     {
+       for (x = g_xx; x <= g_xx + g_ww; x++)
+         {
+            if (!wd->markers[wd->zoom]) continue;
+            eina_matrixsparse_cell_idx_get(wd->markers[wd->zoom], y, x, &cell);
+            if (!cell) continue;
+            wd->cells_displayed = eina_list_append(wd->cells_displayed, cell);
+            markers = eina_matrixsparse_cell_data_get(cell);
+            EINA_LIST_FOREACH(markers, l, group)
+              {
+                 if (!group->markers) continue;
+                 if (group->clas->zoom_displayed > wd->zoom) continue;
+
+                 xx = group->x;
+                 yy = group->y;
+                 ww = group->w;
+                 hh = group->h;
+
+                 if (eina_list_count(group->markers) == 1)
+                   {
+                      Elm_Map_Marker *m = eina_list_data_get(group->markers);
+                      ww = m->clas->priv.edje_w;
+                      hh = m->clas->priv.edje_h;
+                   }
+
+                 if (ww <= 0) ww = 1;
+                 if (hh <= 0) hh = 1;
+
+                 if ((gw != g->w) && (g->w > 0))
+                   {
+                      tx = xx;
+                      xx = ((long long )gw * xx) / g->w;
+                      ww = (((long long)gw * (tx + ww)) / g->w) - xx;
+                   }
+                 if ((gh != g->h) && (g->h > 0))
+                   {
+                      ty = yy;
+                      yy = ((long long)gh * yy) / g->h;
+                      hh = (((long long)gh * (ty + hh)) / g->h) - yy;
+                   }
+
+                 if ((!group->clas->hide)
+                      && (xx-px+ax+ox >= ox) && (xx-px+ax+ox<= ox+ow)
+                      && (yy-py+ay+oy >= oy) && (yy-py+ay+oy<= oy+oh))
+                   {
+                      if (!group->obj) _group_object_create(group);
+
+                      if (group->update_nbelems)
+                        {
+                           group->update_nbelems = EINA_FALSE;
+                           if (eina_list_count(group->markers) > 1)
+                             {
+                                snprintf(buf, sizeof(buf), "%d", eina_list_count(group->markers));
+                                edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", buf);
+                             }
+                           else
+                             edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", "");
+                        }
+                      evas_object_move(group->obj,
+                                        xx - px + ax + ox - ww/2,
+                                        yy - py + ay + oy - hh/2);
+                      if ((!wd->paused_markers) || (group->update_resize))
+                        {
+                           group->update_resize = EINA_FALSE;
+                           evas_object_resize(group->obj, ww, hh);
+                        }
+                      if (group->update_raise)
+                        {
+                           group->update_raise = EINA_FALSE;
+                           evas_object_raise(group->obj);
+                           evas_object_show(group->obj);
+                        }
+                      if (group->bubble) _group_bubble_place(group);
+                   }
+                 else if (group->obj)
+                   {
+                      _group_object_free(group);
+                   }
+              }
+         }
+     }
+}
+
+static void
+grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord ax, ay, gw, gh, tx, ty;
+   int xx, yy, ww, hh;
+
+   if (!wd) return;
+   
+   ax = 0;
+   ay = 0;
+   gw = wd->size.w;
+   gh = wd->size.h;
+   if (ow > gw) ax = (ow - gw) / 2;
+   if (oh > gh) ay = (oh - gh) / 2;
+
+   Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
+   Eina_Matrixsparse_Cell *cell;
+
+   EINA_ITERATOR_FOREACH(it, cell)
+     {
+       Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
+
+       xx = gi->out.x;
+       yy = gi->out.y;
+       ww = gi->out.w;
+       hh = gi->out.h;
+       if ((gw != g->w) && (g->w > 0))
+         {
+            tx = xx;
+            xx = ((long long )gw * xx) / g->w;
+            ww = (((long long)gw * (tx + ww)) / g->w) - xx;
+         }
+       if ((gh != g->h) && (g->h > 0))
+         {
+            ty = yy;
+            yy = ((long long)gh * yy) / g->h;
+            hh = (((long long)gh * (ty + hh)) / g->h) - yy;
+         }
+       evas_object_move(gi->img,
+                         xx - px + ax + ox,
+                         yy - py + ay + oy);
+        
+       evas_object_resize(gi->img, ww, hh);
+
+       /*evas_object_move(gi->txt,
+         xx - px + ax + ox,
+         yy - py + ay + oy);
+
+         evas_object_resize(gi->txt, ww, hh);
+         */
+     }
+   eina_iterator_free(it);
+}
+
+static void
+grid_clear(Evas_Object *obj, Grid *g)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char buf[PATH_MAX];
+
+   if (!wd) return;
+   if (!g->grid) return;
+
+   Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
+   Eina_Matrixsparse_Cell *cell;
+
+   snprintf(buf, sizeof(buf), DEST_DIR_ZOOM_PATH, wd->id, g->zoom);
+   ecore_file_recursive_rm(buf);
+
+   EINA_ITERATOR_FOREACH(it, cell)
+     {
+       Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
+       evas_object_del(gi->img);
+       //evas_object_del(gi->txt);
+
+       if (gi->want)
+         {
+            gi->want = EINA_FALSE;
+            wd->preload_num--;
+            if (!wd->preload_num)
+              {
+                 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                       "elm,state,busy,stop", "elm");
+                 evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
+              }
+         }
+
+       if (gi->job)
+         {
+            DBG("DOWNLOAD abort %s", gi->file);
+            ecore_file_download_abort(gi->job);
+            ecore_file_remove(gi->file);
+            gi->job = NULL;
+            wd->try_num--;
+         }
+       if (gi->file)
+         eina_stringshare_del(gi->file);
+        
+       free(gi);
+     }
+   eina_matrixsparse_free(g->grid);
+   eina_iterator_free(it);
+   g->grid = NULL;
+   g->gw = 0;
+   g->gh = 0;
+}
+
+static void
+_tile_update(Grid_Item *gi)
+{
+   gi->want = EINA_FALSE;
+   gi->download = EINA_FALSE;
+   evas_object_image_file_set(gi->img, gi->file, NULL);
+   if (evas_object_image_load_error_get(gi->img) != EVAS_LOAD_ERROR_NONE)
+     ecore_file_remove(gi->file);
+   
+   evas_object_show(gi->img);
+
+   //evas_object_text_text_set(gi->txt, gi->file);
+   //evas_object_show(gi->txt);
+
+   gi->have = EINA_TRUE;
+   gi->wd->preload_num--;
+   if (!gi->wd->preload_num)
+     {
+       edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr),
+                                "elm,state,busy,stop", "elm");
+       evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL);
+     }
+}
+
+
+static void
+_tile_downloaded(void *data, const char *file __UNUSED__, int status)
+{
+   Grid_Item *gi = data;
+
+   gi->download = EINA_FALSE;
+   gi->job = NULL;
+
+   DBG("DOWNLOAD done %s", gi->file);
+   if ((gi->want) && (!status)) _tile_update(gi);
+
+   if (status)
+     {
+       DBG("Download failed %s (%d) ", gi->file, status);
+       ecore_file_remove(gi->file);
+     }
+   else
+     gi->wd->finish_num++;
+
+   evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL);
+}
+
+static Grid *
+grid_create(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Grid *g;
+
+   g = calloc(1, sizeof(Grid));
+
+   g->zoom = wd->zoom;
+   g->tsize = wd->tsize;
+   g->wd = wd;
+
+   if (g->zoom > map_sources_tab[wd->source].zoom_max) return NULL;
+   if (g->zoom < map_sources_tab[wd->source].zoom_min) return NULL;
+
+   int size =  pow(2.0, wd->zoom);
+   g->gw = size;
+   g->gh = size;
+
+   g->w = g->tsize * g->gw;
+   g->h = g->tsize * g->gh;
+
+   g->grid = eina_matrixsparse_new(g->gh, g->gw, NULL, NULL);
+
+   return g;
+}
+
+static void
+grid_load(Evas_Object *obj, Grid *g)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int x, y;
+   int size;
+   Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, tx, ty, gw, gh, xx, yy, ww, hh;
+   Eina_Iterator *it;
+   Eina_Matrixsparse_Cell *cell;
+   Grid_Item *gi;
+
+   if (!wd) return;
+   evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
+   evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh);
+                               
+   gw = wd->size.w;
+   gh = wd->size.h;
+
+   if ((gw <= 0) || (gh <= 0)) return;
+
+   size = g->tsize;
+   if ((gw != g->w) && (g->w > 0))
+     size = ((long long)gw * size) / g->w;
+   if (size < (g->tsize / 2)) return; // else we will load to much tiles
+
+   it = eina_matrixsparse_iterator_new(g->grid);
+   
+   EINA_ITERATOR_FOREACH(it, cell)
+     {
+       gi = eina_matrixsparse_cell_data_get(cell);
+
+       xx = gi->out.x;
+       yy = gi->out.y;
+       ww = gi->out.w;
+       hh = gi->out.h;
+
+       if ((gw != g->w) && (g->w > 0))
+         {
+            tx = xx;
+            xx = ((long long )gw * xx) / g->w;
+            ww = (((long long)gw * (tx + ww)) / g->w) - xx;
+         }
+       if ((gh != g->h) && (g->h > 0))
+         {
+            ty = yy;
+            yy = ((long long)gh * yy) / g->h;
+            hh = (((long long)gh * (ty + hh)) / g->h) - yy;
+         }
+
+        if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox, 
+                                 yy  - wd->pan_y + oy,
+                                 ww, hh,
+                                 cvx, cvy, cvw, cvh))
+         {
+            if (gi->want)
+              {
+                 evas_object_hide(gi->img);
+                 //evas_object_hide(gi->txt);
+                 evas_object_image_file_set(gi->img, NULL, NULL);
+                 gi->want = EINA_FALSE;
+                 gi->have = EINA_FALSE;
+                  
+                 if (gi->job)
+                   {
+                      DBG("DOWNLOAD abort %s", gi->file);
+                      ecore_file_download_abort(gi->job);
+                      ecore_file_remove(gi->file);
+                      gi->job = NULL;
+                       wd->try_num--;
+                   }
+                 gi->download = EINA_FALSE;
+                 wd->preload_num--;
+                 if (!wd->preload_num)
+                   {
+                      edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                                               "elm,state,busy,stop", "elm");
+                      evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL,
+                                                      NULL);
+                   }
+
+              }
+            else if (gi->have)
+              {
+                 evas_object_hide(gi->img);
+                 //evas_object_hide(gi->txt);
+                 evas_object_image_preload(gi->img, 1);
+                 evas_object_image_file_set(gi->img, NULL, NULL);
+                 gi->have = EINA_FALSE;
+                 gi->want = EINA_FALSE;
+              }
+         }
+     }
+   eina_iterator_free(it);
+
+   xx = wd->pan_x / size;
+   if (xx < 0) xx = 0;
+
+   yy = wd->pan_y / size;
+   if (yy < 0) yy = 0;
+
+   ww = ow / size + 1;
+   if (xx + ww >= g->gw) ww = g->gw - xx - 1;
+
+   hh = oh / size + 1;
+   if (yy + hh >= g->gh) hh = g->gh - yy - 1;
+
+   for (y = yy; y <= yy + hh; y++)
+     {
+       for (x = xx; x <= xx + ww; x++)
+         {
+            gi = eina_matrixsparse_data_idx_get(g->grid, y, x);
+
+            if ((!gi) && (g != eina_list_data_get(wd->grids)))
+              continue;
+
+            if (!gi)
+              {
+                 gi = calloc(1, sizeof(Grid_Item));
+                 gi->src.x = x * g->tsize;
+                 gi->src.y = y * g->tsize;
+                 gi->src.w = g->tsize;
+                 gi->src.h = g->tsize;
+
+                 gi->out.x = gi->src.x;
+                 gi->out.y = gi->src.y;
+                 gi->out.w = gi->src.w;
+                 gi->out.h = gi->src.h;
+
+                 gi->wd = wd;
+                  
+                 gi->img = evas_object_image_add(evas_object_evas_get(obj));
+                 evas_object_image_scale_hint_set
+                    (gi->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
+                 evas_object_image_filled_set(gi->img, 1);
+                  
+                 evas_object_smart_member_add(gi->img, wd->pan_smart);
+                 elm_widget_sub_object_add(obj, gi->img);
+                 evas_object_pass_events_set(gi->img, EINA_TRUE);
+                 evas_object_stack_below(gi->img, wd->sep_maps_markers);
+                  
+                 /*gi->txt = evas_object_text_add(evas_object_evas_get(obj));
+                   evas_object_text_font_set(gi->txt, "Vera", 12);
+                   evas_object_color_set(gi->txt, 100, 100, 100, 255);
+                   evas_object_smart_member_add(gi->txt,
+                   wd->pan_smart);
+                   elm_widget_sub_object_add(obj, gi->txt);
+                   evas_object_pass_events_set(gi->txt, EINA_TRUE);
+                   */
+                 eina_matrixsparse_data_idx_set(g->grid, y, x, gi);
+              }
+             
+            if ((!gi->have) && (!gi->download))
+              {
+                 char buf[PATH_MAX], buf2[PATH_MAX];
+                 char *source;
+                  
+                 gi->want = EINA_TRUE;
+                  
+                 snprintf(buf, sizeof(buf), DEST_DIR_PATH, wd->id, g->zoom, x);
+                 if (!ecore_file_exists(buf))
+                   ecore_file_mkpath(buf);
+                  
+                 snprintf(buf2, sizeof(buf2), DEST_FILE_PATH, buf, y);
+                  
+                 source = map_sources_tab[wd->source].url_cb(obj, x, y, g->zoom);
+                 if ((!source) || (strlen(source)==0)) continue;
+                  
+                 eina_stringshare_replace(&gi->file, buf2);
+
+                 if ((ecore_file_exists(buf2)) || (g == eina_list_data_get(wd->grids)))
+                   {
+                      gi->download = EINA_TRUE;
+                      wd->preload_num++;
+                      if (wd->preload_num == 1)
+                        {
+                           edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                                                    "elm,state,busy,start", "elm");
+                           evas_object_smart_callback_call(obj,
+                                                           SIG_LOAD_DETAIL,
+                                                           NULL);
+                        }
+                       
+                      if (ecore_file_exists(buf2))
+                        _tile_update(gi);
+                      else
+                        {
+                           DBG("DOWNLOAD %s \t in %s", source, buf2);
+                           ecore_file_download(source, buf2, _tile_downloaded, NULL, gi, &(gi->job));
+                            if (!gi->job)
+                              DBG("Can't start to download %s", buf);
+                            else
+                              wd->try_num++;
+                        }
+                   }
+                 if (source) free(source);
+              }
+            else if (gi->have)
+              evas_object_show(gi->img);
+         }
+     }
+}
+
+static void
+grid_clearall(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Grid *g;
+
+   if (!wd) return;
+   EINA_LIST_FREE(wd->grids, g)
+     {
+       grid_clear(obj, g);
+       free(g);
+     }
+}
+
+static void
+_smooth_update(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Grid *g;
+
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->grids, l, g)
+     {
+       Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
+       Eina_Matrixsparse_Cell *cell;
+        
+       EINA_ITERATOR_FOREACH(it, cell)
+         {
+            Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
+            evas_object_image_smooth_scale_set(gi->img, (!wd->nosmooth));
+         }
+       eina_iterator_free(it);
+     }
+}
+
+static void
+_grid_raise(Grid *g)
+{
+   Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
+   Eina_Matrixsparse_Cell *cell;
+
+   g->wd->size.w = g->w;
+   g->wd->size.h = g->h;
+
+   EINA_ITERATOR_FOREACH(it, cell)
+     {
+       Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
+       evas_object_raise(gi->img);
+       //evas_object_raise(gi->txt);
+     }
+   eina_iterator_free(it);
+}
+
+static Eina_Bool
+_scr_timeout(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->nosmooth--;
+   if (!wd->nosmooth) _smooth_update(data);
+   wd->scr_timer = NULL;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (!wd->scr_timer)
+     {
+       wd->nosmooth++;
+       if (wd->nosmooth == 1) _smooth_update(data);
+     }
+   if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
+   wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data);
+}
+
+static Eina_Bool
+zoom_do(Evas_Object *obj, double t)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord xx, yy, ow, oh;
+
+   if (!wd) return 0;
+   if (t > 1.0) t = 1.0;
+
+   wd->size.w = (wd->size.ow * (1.0 - t)) + (wd->size.nw * t);
+   wd->size.h = (wd->size.oh * (1.0 - t)) + (wd->size.nh * t);
+
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh);
+
+   if (wd->center_on.enabled)
+     {
+       elm_map_utils_convert_geo_into_coord(obj, wd->center_on.lon, wd->center_on.lat, wd->size.w, &xx, &yy);
+       xx -= ow / 2;
+       yy -= oh / 2;
+     }
+   else
+     {
+       xx = (wd->size.spos.x * wd->size.w) - (ow / 2);
+       yy = (wd->size.spos.y * wd->size.h) - (oh / 2);
+     }
+
+   if (xx < 0) xx = 0;
+   else if (xx > (wd->size.w - ow)) xx = wd->size.w - ow;
+   if (yy < 0) yy = 0;
+   else if (yy > (wd->size.h - oh)) yy = wd->size.h - oh;
+
+   wd->show.show = EINA_TRUE;
+   wd->show.x = xx;
+   wd->show.y = yy;
+   wd->show.w = ow;
+   wd->show.h = oh;
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   if (t >= 1.0)
+     {
+       return ECORE_CALLBACK_CANCEL;
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_zoom_anim(void *data)
+{
+   Evas_Object *obj = data;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double t;
+   int go;
+
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   t = ecore_loop_time_get();
+   if (t >= wd->t_end)
+     t = 1.0;
+   else if (wd->t_end > wd->t_start)
+     t = (t - wd->t_start) / (wd->t_end - wd->t_start);
+   else
+     t = 1.0;
+   t = 1.0 - t;
+   t = 1.0 - (t * t);
+   go = zoom_do(obj, t);
+   if (!go)
+     {
+       wd->nosmooth--;
+       if (!wd->nosmooth) _smooth_update(data);
+       wd->zoom_animator = NULL;
+       evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
+     }
+   return go;
+}
+
+static Eina_Bool
+_long_press(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->long_timer = NULL;
+   wd->longpressed = EINA_TRUE;
+   evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Down *ev = event_info;
+   Event *ev0;
+   
+   ev0 = get_event_object(data, 0);
+   if (ev0) return;
+   ev0 = create_event_object(data, obj, 0);
+   if (!ev0) return;
+
+   ev0->hold_timer = NULL;
+   ev0->prev.x = ev->output.x;
+   ev0->prev.y = ev->output.y;
+
+   if (!wd) return;
+   if (ev->button != 1) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
+   else wd->on_hold = EINA_FALSE;
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+      evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, ev);
+   else
+      evas_object_smart_callback_call(data, SIG_PRESS, ev);
+   wd->longpressed = EINA_FALSE;
+   if (wd->long_timer) ecore_timer_del(wd->long_timer);
+   wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
+}
+
+static void
+_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Move *move = event_info;
+   Event *ev0;
+   
+   if (wd->pinch_zoom) return;
+   ev0 = get_event_object(data, 0);
+   if (!ev0) return;
+   ev0->prev.x = move->cur.output.x;
+   ev0->prev.y = move->cur.output.y;
+}
+
+static void
+_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Up *ev = event_info;
+   int mdevice;
+   Event *ev0;
+   Event *ev1;
+   
+   ev0 = get_event_object(data, 0);
+   if (ev0)
+     {
+        mdevice = get_multi_device(data);
+        if (mdevice == 0)
+          {
+             if (ev0->hold_timer)
+               {
+                  ecore_timer_del(ev0->hold_timer);
+                  ev0->hold_timer = NULL;
+               }
+             elm_smart_scroller_hold_set(wd->scr, 0);
+             elm_smart_scroller_freeze_set(wd->scr, 0);
+             wd->pinch_zoom = EINA_FALSE;
+          }
+        else
+          {
+             ev1 = get_event_object(data, mdevice);
+             if (ev1) 
+                ev1->hold_timer = ecore_timer_add(0.35, _hold_timer_cb, ev1);
+          }
+        destroy_event_object(data, ev0);
+     }
+
+   if (!wd) return;
+   if (ev->button != 1) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
+   else wd->on_hold = EINA_FALSE;
+   if (wd->long_timer)
+     {
+       ecore_timer_del(wd->long_timer);
+       wd->long_timer = NULL;
+     }
+   if (!wd->on_hold) evas_object_smart_callback_call(data, SIG_CLICKED, ev);
+   wd->on_hold = EINA_FALSE;
+}
+
+static void
+_mouse_multi_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Event *ev;
+   Evas_Event_Multi_Down *down = event_info;
+
+   elm_smart_scroller_hold_set(wd->scr, 1);
+   elm_smart_scroller_freeze_set(wd->scr, 1);
+
+   ev = get_event_object(data, down->device);
+   if (ev) goto done;
+
+   ev = create_event_object(data, obj, down->device);
+   if (!ev)
+     {
+        DBG("Failed : create_event_object");
+        goto done;
+     }
+
+   wd->pinch_zoom = EINA_FALSE;
+
+   ev->hold_timer = NULL;
+   ev->prev.x = down->output.x;
+   ev->prev.y = down->output.y;
+
+done:
+   return;
+}
+
+static void
+_mouse_multi_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Multi_Move *move = event_info;
+   int dis_new, zoom;
+   Event *ev0;
+   Event *ev;
+
+   if (wd->pinch_zoom) return;
+   ev = get_event_object(data, move->device);
+   if (!ev) return;
+
+   ev->prev.x = move->cur.output.x;
+   ev->prev.y = move->cur.output.y;
+
+   ev0 = get_event_object(data, 0);
+   if (!ev0) return;
+
+   dis_new = get_distance(ev0->prev.x, ev0->prev.y, ev->prev.x, ev->prev.y);
+   zoom = wd->zoom;
+   
+   if (dis_old)
+     {
+        if (((dis_old - dis_new) > 0) && 
+            (ev->pinch_dis > elm_finger_size_get()))
+          {
+             wd->pinch_zoom = EINA_TRUE;
+             zoom--;
+             elm_map_zoom_set(data, zoom);
+             ev->pinch_dis = 0;
+          }
+        else if (((dis_old - dis_new) < 0) && 
+                 (ev->pinch_dis < -elm_finger_size_get()))
+          {
+             wd->pinch_zoom = EINA_TRUE;
+             zoom++;
+             elm_map_zoom_set(data, zoom);
+             ev->pinch_dis = 0;
+          }
+        ev->pinch_dis += (dis_old - dis_new);
+     }
+   dis_old = dis_new;
+}
+
+static void
+_mouse_multi_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Multi_Up *up = event_info;
+   Event *ev0;
+   Event *ev;
+
+   ev = get_event_object(data, up->device);
+   if (!ev)
+     {
+        DBG("Cannot get multi device");
+        return;
+     }
+   dis_old = 0;
+   
+   ev0 = get_event_object(data, 0);
+   if (ev0)
+      ev0->hold_timer = ecore_timer_add(0.35, _hold_timer_cb, ev0);
+   else
+     {
+        if (ev->hold_timer)
+          {
+             ecore_timer_del(ev->hold_timer);
+             ev->hold_timer = NULL;
+          }   
+     }
+   destroy_event_object(data, ev);
+}
+
+static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL;
+
+static Eina_Bool
+_hold_timer_cb(void *data)
+{
+   Event *ev0 = data;
+   
+   ev0->hold_timer = NULL;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void 
+_rect_resize_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   int x, y, w, h;
+
+   evas_object_geometry_get(wd->rect, &x, &y, &w, &h);
+   evas_object_geometry_get(wd->pan_smart, &x, &y, &w, &h);
+   evas_object_resize(wd->rect, w, h);
+   evas_object_move(wd->rect, x, y);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Elm_Map_Group_Class *group_clas;
+   Elm_Map_Marker_Class *marker_clas;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Event *ev;
+
+   if (!wd) return;
+
+   EINA_LIST_FREE(wd->groups_clas, group_clas)
+     {
+       if (group_clas->style)
+         eina_stringshare_del(group_clas->style);
+       free(group_clas);
+     }
+
+   EINA_LIST_FREE(wd->markers_clas, marker_clas)
+     {
+       if (marker_clas->style)
+         eina_stringshare_del(marker_clas->style);
+       free(marker_clas);
+     }
+
+   EINA_LIST_FOREACH(wd->s_event_list, l, ev)
+     {
+        destroy_event_object(obj, ev);
+     }
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
+   if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
+   if (wd->long_timer) ecore_timer_del(wd->long_timer);
+   if ((wd->api) && (wd->api->obj_unhook)) wd->api->obj_unhook(obj);
+
+   free(wd);
+}
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Marker_Group *group;
+   Elm_Map_Marker *marker;
+   int i;
+   Eina_Bool free_marker = EINA_TRUE;
+   Eina_List *l;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   grid_clearall(obj);
+
+   if (!wd) return;
+   for (i = 0; i < ZOOM_MAX + 1; i++)
+     {
+       if (!wd->markers[i]) continue;
+       Eina_Iterator *it = eina_matrixsparse_iterator_new(wd->markers[i]);
+       Eina_Matrixsparse_Cell *cell;
+        
+       EINA_ITERATOR_FOREACH(it, cell)
+         {
+            l =  eina_matrixsparse_cell_data_get(cell);
+            EINA_LIST_FREE(l, group)
+              {
+                 EINA_LIST_FREE(group->markers, marker)
+                   {
+                      evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                                           _bubble_sc_hits_changed_cb, group);
+                      if (free_marker) free(marker);
+                   }
+                 free(group);
+              }
+            free_marker = EINA_FALSE;
+         }
+       eina_iterator_free(it);
+       eina_matrixsparse_free(wd->markers[i]);
+     }
+
+   evas_object_del(wd->sep_maps_markers);
+   evas_object_del(wd->pan_smart);
+   wd->pan_smart = NULL;
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->obj, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->obj, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->obj, EINA_FALSE);
+     }
+}
+
+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, "map", "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
+_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
+_calc_job(void *data)
+{
+   Widget_Data *wd = data;
+   Evas_Coord minw, minh;
+
+   minw = wd->size.w;
+   minh = wd->size.h;
+   if (wd->resized)
+     {
+       wd->resized = 0;
+       if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
+         {
+            double tz = wd->zoom;
+            wd->zoom = 0.0;
+            elm_map_zoom_set(wd->obj, tz);
+         }
+     }
+   if ((minw != wd->minw) || (minh != wd->minh))
+     {
+       wd->minw = minw;
+       wd->minh = minh;
+       evas_object_smart_callback_call(wd->pan_smart, SIG_CHANGED, NULL);
+       _sizing_eval(wd->obj);
+     }
+   wd->calc_job = NULL;
+   evas_object_smart_changed(wd->pan_smart);
+}
+
+static void
+_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   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 (!sd) return;
+   if (x) *x = sd->wd->pan_x;
+   if (y) *y = sd->wd->pan_y;
+}
+
+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);
+   ow = sd->wd->minw - ow;
+   if (ow < 0) ow = 0;
+   oh = sd->wd->minh - oh;
+   if (oh < 0) oh = 0;
+   if (x) *x = ow;
+   if (y) *y = oh;
+}
+
+static void
+_pan_min_get(Evas_Object *obj __UNUSED__, Evas_Coord *x, Evas_Coord *y)
+{
+   if (x) *x = 0;
+   if (y) *y = 0;
+}
+
+static void
+_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (w) *w = sd->wd->minw;
+   if (h) *h = sd->wd->minh;
+}
+
+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);
+   if (!cd) return;
+   sd = calloc(1, sizeof(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_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   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 ((ow == w) && (oh == h)) return;
+   sd->wd->resized = 1;
+   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 ox, oy, ow, oh;
+   Eina_List *l;
+   Grid *g;
+   if (!sd) return;
+   evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
+   rect_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+   EINA_LIST_FOREACH(sd->wd->grids, l, g)
+     {
+       grid_load(sd->wd->obj, g);
+       grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+       marker_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+     }
+}
+
+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_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "scroll,anim,start", NULL);
+}
+
+static void
+_scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "scroll,anim,stop", NULL);
+}
+
+static void
+_scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   wd->center_on.enabled = EINA_FALSE;
+   evas_object_smart_callback_call(data, SIG_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, SIG_SCROLL_DRAG_STOP, NULL);
+}
+
+static void
+_scr_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
+}
+
+
+static void
+_group_object_create(Marker_Group *group)
+{
+   const char *style = "radio";
+   Evas_Object *icon = NULL;
+
+   if (group->obj) return;
+   if ((!group->clas->priv.objs_notused) || (eina_list_count(group->markers) == 1))
+     {
+       //set icon and style
+       if (eina_list_count(group->markers) == 1)
+         {
+            Elm_Map_Marker *m = eina_list_data_get(group->markers);
+            if (m->clas->style)
+              style = m->clas->style;
+             
+            if (m->clas->func.icon_get)
+              icon = m->clas->func.icon_get(group->wd->obj, m, m->data);
+             
+            group->delete_object = EINA_TRUE;
+         }
+       else
+         {
+            if (group->clas->style)
+              style = group->clas->style;
+             
+            if (group->clas->func.icon_get)
+              icon = group->clas->func.icon_get(group->wd->obj, group->clas->data);
+             
+            group->delete_object = EINA_FALSE;
+         }
+        
+       group->obj = elm_layout_add(group->wd->obj);
+       elm_layout_theme_set(group->obj, "map/marker", style, elm_widget_style_get(group->wd->obj));
+
+       if (icon) elm_layout_content_set(group->obj, "elm.icon", icon);
+        
+       evas_object_smart_member_add(group->obj, group->wd->pan_smart);
+       elm_widget_sub_object_add(group->wd->obj, group->obj);
+       evas_object_stack_above(group->obj, group->wd->sep_maps_markers);
+
+       if (!group->delete_object)
+         group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj);
+     }
+   else
+     {
+       group->delete_object = EINA_FALSE;
+        
+       group->obj = eina_list_data_get(group->clas->priv.objs_notused);
+       group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj);
+       group->clas->priv.objs_notused = eina_list_remove(group->clas->priv.objs_notused, group->obj);
+       evas_object_show(group->obj);
+     }
+
+   edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb, group);
+   edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb, group);
+
+   group->update_nbelems = EINA_TRUE;
+   group->update_resize = EINA_TRUE;
+   group->update_raise = EINA_TRUE;
+
+   if (group->open) _group_bubble_create(group);
+}
+
+static void
+_group_object_free(Marker_Group *group)
+{
+   if (!group->obj) return;
+   if (!group->delete_object)
+     {
+       group->clas->priv.objs_notused = eina_list_append(group->clas->priv.objs_notused, group->obj);
+       group->clas->priv.objs_used = eina_list_remove(group->clas->priv.objs_used, group->obj);
+       evas_object_hide(group->obj);
+
+       edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb);
+       edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb);
+     }
+   else
+     evas_object_del(group->obj);
+
+   group->obj = NULL;
+   _group_bubble_free(group);
+}
+
+static void
+_group_bubble_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Marker_Group *group = data;
+
+   if (!evas_object_above_get(group->rect)) return;
+   evas_object_raise(group->bubble);
+   evas_object_raise(group->sc);
+   evas_object_raise(group->rect);
+}
+
+static void
+_group_bubble_create(Marker_Group *group)
+{
+   if (group->bubble) return;
+
+   group->wd->opened_bubbles = eina_list_append(group->wd->opened_bubbles, group);
+   group->bubble = edje_object_add(evas_object_evas_get(group->obj));
+   _elm_theme_object_set(group->wd->obj, group->bubble, "map", "marker_bubble",
+                         elm_widget_style_get(group->wd->obj));
+   evas_object_smart_member_add(group->bubble,
+                                group->wd->obj);
+   elm_widget_sub_object_add(group->wd->obj, group->bubble);
+   
+   _group_bubble_content_free(group);
+   if (!_group_bubble_content_update(group))
+     {
+       //no content, we can delete the bubble
+       _group_bubble_free(group);
+       return;
+     }
+   
+   group->rect = evas_object_rectangle_add(evas_object_evas_get(group->obj));
+   evas_object_color_set(group->rect, 0, 0, 0, 0);
+   evas_object_repeat_events_set(group->rect, EINA_TRUE);
+   evas_object_smart_member_add(group->rect, group->wd->obj);
+   elm_widget_sub_object_add(group->wd->obj, group->rect);
+   
+   evas_object_event_callback_add(group->rect, EVAS_CALLBACK_MOUSE_UP, _group_bubble_mouse_up_cb, group);
+   
+   _group_bubble_place(group);
+}
+
+static void _bubble_sc_hits_changed_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _group_bubble_place(data);
+}
+
+static int
+_group_bubble_content_update(Marker_Group *group)
+{
+   Eina_List *l;
+   Elm_Map_Marker *marker;
+   int i = 0;
+
+   if (!group->bubble) return 1;
+
+   if (!group->sc)
+     {
+       group->sc = elm_scroller_add(group->bubble);
+       elm_scroller_content_min_limit(group->sc, EINA_FALSE, EINA_TRUE);
+       elm_scroller_policy_set(group->sc, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
+       elm_scroller_bounce_set(group->sc, _elm_config->thumbscroll_bounce_enable, EINA_FALSE);
+       edje_object_part_swallow(group->bubble, "elm.swallow.content", group->sc);
+       evas_object_show(group->sc);
+       evas_object_smart_member_add(group->sc,
+                                     group->wd->obj);
+       elm_widget_sub_object_add(group->wd->obj, group->sc);
+        
+       group->bx = elm_box_add(group->bubble);
+       evas_object_size_hint_align_set(group->bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       evas_object_size_hint_weight_set(group->bx, 0.5, 0.5);
+       elm_box_horizontal_set(group->bx, EINA_TRUE);
+       evas_object_show(group->bx);
+        
+       elm_scroller_content_set(group->sc, group->bx);
+        
+       evas_object_event_callback_add(group->sc, EVAS_CALLBACK_RESIZE,
+                                       _bubble_sc_hits_changed_cb, group);
+     }
+   
+   EINA_LIST_FOREACH(group->markers, l, marker)
+     {
+       if (i >= group->wd->markers_max_num) break;
+       if ((!marker->content) && (marker->clas->func.get))
+         marker->content = marker->clas->func.get(group->wd->obj, marker, marker->data);
+       else if (marker->content)
+         elm_box_unpack(group->bx, marker->content);
+       if (marker->content)
+         {
+            elm_box_pack_end(group->bx, marker->content);
+            i++;
+         }
+     }
+   return i;
+}
+
+static void
+_group_bubble_content_free(Marker_Group *group)
+{
+   Eina_List *l;
+   Elm_Map_Marker *marker;
+
+   if (!group->sc) return;
+   EINA_LIST_FOREACH(group->markers, l, marker)
+     {
+       if ((marker->content) && (marker->clas->func.del))
+         marker->clas->func.del(group->wd->obj, marker, marker->data, marker->content);
+       else if (marker->content)
+         evas_object_del(marker->content);
+       marker->content = NULL;
+     }
+   evas_object_del(group->sc);
+   group->sc = NULL;
+}
+
+static void
+_group_bubble_free(Marker_Group *group)
+{
+   if (!group->bubble) return;
+   group->wd->opened_bubbles = eina_list_remove(group->wd->opened_bubbles, group);
+   evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _bubble_sc_hits_changed_cb, group);
+   evas_object_del(group->bubble);
+   evas_object_del(group->rect);
+   group->bubble = NULL;
+   _group_bubble_content_free(group);
+}
+
+static void
+_group_bubble_place(Marker_Group *group)
+{
+   Evas_Coord x, y, w;
+   Evas_Coord xx, yy, ww, hh;
+   const char *s;
+
+   if ((!group->bubble) || (!group->obj)) return;
+
+   evas_object_geometry_get(group->obj, &x, &y, &w, NULL);
+   edje_object_size_min_calc(group->bubble, NULL, &hh);
+
+   s = edje_object_data_get(group->bubble, "size_w");
+   ww = atoi(s);
+   xx = x + w / 2 - ww / 2;
+   yy = y-hh;
+
+   evas_object_move(group->bubble, xx, yy);
+   evas_object_resize(group->bubble, ww, hh);
+   evas_object_show(group->bubble);
+
+   evas_object_move(group->rect, xx, yy);
+   evas_object_resize(group->rect, ww, hh);
+   evas_object_show(group->rect);
+}
+
+static void
+_group_bringin_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__)
+{
+   Marker_Group *group = data;
+   Elm_Map_Marker *marker = eina_list_data_get(group->markers);
+   if (!marker) return;
+   group->bringin = EINA_TRUE;
+   elm_map_geo_region_bring_in(group->wd->obj, marker->longitude, marker->latitude);
+}
+
+static void
+_group_open_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__)
+{
+   Marker_Group *group = data;
+
+   if (group->bringin)
+     {
+       group->bringin = EINA_FALSE;
+       return;
+     }
+
+   if (group->bubble)
+     {
+       group->open = EINA_FALSE;
+       _group_bubble_free(group);
+       return;
+     }
+   group->open = EINA_TRUE;
+   _group_bubble_create(group);
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   double zoom;
+   Evas_Coord x = 0;
+   Evas_Coord y = 0;
+   Evas_Coord step_x = 0;
+   Evas_Coord step_y = 0;
+   Evas_Coord v_w = 0;
+   Evas_Coord v_h = 0;
+   Evas_Coord page_x = 0;
+   Evas_Coord page_y = 0;
+
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+
+   elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
+   elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
+   elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
+
+   if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
+     {
+        x -= step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
+     {
+        x += step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Up"))  || (!strcmp(ev->keyname, "KP_Up")))
+     {
+        y -= step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
+     {
+        y += step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
+     {
+        if (page_y < 0)
+           y -= -(page_y * v_h) / 100;
+        else
+           y -= page_y;
+     }
+   else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
+     {
+        if (page_y < 0)
+           y += -(page_y * v_h) / 100;
+        else
+           y += page_y;
+     }
+   else if (!strcmp(ev->keyname, "KP_Add"))
+     {
+        zoom = elm_map_zoom_get(obj);
+        zoom += 1;
+        elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL);
+        elm_map_zoom_set(obj, zoom);
+        return EINA_TRUE;
+     }
+   else if (!strcmp(ev->keyname, "KP_Subtract"))
+     {
+        zoom = elm_map_zoom_get(obj);
+        zoom -= 1;
+        elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL);
+        elm_map_zoom_set(obj, zoom);
+        return EINA_TRUE;
+     }
+   else return EINA_FALSE;
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   elm_smart_scroller_child_pos_set(wd->scr, x, y);
+
+   return EINA_TRUE;
+}
+
+static int idnum = 1;
+
+/**
+ * Add a new Map object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Map
+ */
+EAPI Evas_Object *
+elm_map_add(Evas_Object *parent)
+{
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord minw, minh;
+   Evas_Object *obj;
+   static Evas_Smart *smart = NULL;
+   Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   if (!ecore_file_download_protocol_available("http://"))
+     {
+       ERR("Ecore must be built with the support of HTTP for the widget map !");
+       return NULL;
+     }
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "map");
+   elm_widget_type_set(obj, "map");
+   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_del_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_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, "map", "base", "default");
+   evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj);
+   evas_object_smart_callback_add(wd->scr, "drag", _scr, obj);
+   elm_widget_resize_object_set(obj, wd->scr);
+
+   evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
+   evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
+   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, bounce, bounce);
+
+   wd->api = module(obj);
+   if ((wd->api) && (wd->api->obj_hook)) wd->api->obj_hook(obj);
+
+   wd->obj = obj;
+
+   wd->markers_max_num = 30;
+   wd->source = ELM_MAP_SOURCE_MAPNIK;
+
+   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_map_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_min_get, _pan_child_size_get);
+
+   wd->rect = evas_object_rectangle_add(e);
+   evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_RESIZE,
+                                  _rect_resize_cb, obj);
+   evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_DOWN,
+        _mouse_down, obj);
+   evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _mouse_move, obj);
+   evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_UP,
+        _mouse_up, obj);
+   evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_DOWN, 
+                                  _mouse_multi_down, obj);
+   evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_MOVE,
+                                  _mouse_multi_move, obj);
+   evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_UP,
+                                  _mouse_multi_up, obj);
+
+   evas_object_smart_member_add(wd->rect, wd->pan_smart);
+   elm_widget_sub_object_add(obj, wd->rect);
+   evas_object_show(wd->rect);
+   evas_object_color_set(wd->rect, 0, 0, 0, 0);
+
+   wd->zoom = -1;
+   wd->mode = ELM_MAP_ZOOM_MODE_MANUAL;
+   wd->id = ((int)getpid() << 16) | idnum;
+   idnum++;
+
+   wd->tsize = 256;
+
+   edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
+                             &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+
+   wd->paused = EINA_TRUE;
+   elm_map_zoom_set(obj, 0);
+   wd->paused = EINA_FALSE;
+
+   _sizing_eval(obj);
+
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+
+   wd->sep_maps_markers = evas_object_rectangle_add(evas_object_evas_get(obj));
+   evas_object_smart_member_add(wd->sep_maps_markers, wd->pan_smart);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the zoom level of the map
+ *
+ * This sets the zoom level. 0 is the world map and 18 is the maximum zoom.
+ *
+ * @param obj The map object
+ * @param zoom The zoom level to set
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_zoom_set(Evas_Object *obj, int zoom)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Grid *g, *g_zoom = NULL;
+   Evas_Coord rx, ry, rw, rh;
+   int z;
+   int zoom_changed = 0, started = 0;
+   
+   if (!wd) return;
+   if (zoom < 0 ) zoom = 0;
+   if (zoom > map_sources_tab[wd->source].zoom_max)
+     zoom = map_sources_tab[wd->source].zoom_max;
+   if (zoom < map_sources_tab[wd->source].zoom_min)
+     zoom = map_sources_tab[wd->source].zoom_min;
+   if (zoom == wd->zoom) return;
+
+   wd->zoom = zoom;
+   wd->size.ow = wd->size.w;
+   wd->size.oh = wd->size.h;
+   elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+
+   if (wd->mode == ELM_MAP_ZOOM_MODE_MANUAL)
+     {
+       wd->size.nw = pow(2.0, wd->zoom) * wd->tsize;
+       wd->size.nh = pow(2.0, wd->zoom) * wd->tsize;
+     }
+   else if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FIT)
+     {
+       int p2w, p2h;
+       int cumulw, cumulh;
+
+       cumulw = wd->tsize;
+       p2w = 0;
+       while (cumulw <= rw)
+         {
+            p2w++;
+            cumulw *= 2;
+         }
+       p2w--;
+
+       cumulh = wd->tsize;
+       p2h = 0;
+       while (cumulh <= rh)
+         {
+            p2h++;
+            cumulh *= 2;
+         }
+       p2h--;
+        
+       if (p2w < p2h)
+         z = p2w;
+       else
+         z = p2h;
+        
+       wd->zoom = z;
+       wd->size.nw = pow(2.0, wd->zoom) * wd->tsize;
+       wd->size.nh = pow(2.0, wd->zoom) * wd->tsize;
+     }
+   else if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FILL)
+     {
+       int p2w, p2h;
+       int cumulw, cumulh;
+        
+       cumulw = wd->tsize;
+       p2w = 0;
+       while (cumulw <= rw)
+         {
+            p2w++;
+            cumulw *= 2;
+         }
+       p2w--;
+
+       cumulh = wd->tsize;
+       p2h = 0;
+       while (cumulh <= rh)
+         {
+            p2h++;
+            cumulh *= 2;
+         }
+       p2h--;
+
+       if (p2w > p2h)
+         z = p2w;
+       else
+         z = p2h;
+        
+       wd->zoom = z;
+       wd->size.nw = pow(2.0, wd->zoom) * wd->tsize;
+       wd->size.nh = pow(2.0, wd->zoom) * wd->tsize;
+     }
+
+   EINA_LIST_FOREACH(wd->grids, l, g)
+     {
+       if (g->zoom == wd->zoom)
+         {
+            wd->grids = eina_list_remove(wd->grids, g);
+            wd->grids = eina_list_prepend(wd->grids, g);
+            _grid_raise(g);
+            goto done;
+         }
+     }
+   g = grid_create(obj);
+   if (g)
+     {
+       if (eina_list_count(wd->grids) > 1)
+         {
+            g_zoom = eina_list_last(wd->grids)->data;
+            wd->grids = eina_list_remove(wd->grids, g_zoom);
+            grid_clear(obj, g_zoom);
+            free(g_zoom);
+         }
+       wd->grids = eina_list_prepend(wd->grids, g);
+     }
+   else
+     {
+       EINA_LIST_FREE(wd->grids, g)
+         {
+            grid_clear(obj, g);
+            free(g);
+         }
+     }
+done:
+
+   wd->t_start = ecore_loop_time_get();
+   wd->t_end = wd->t_start + _elm_config->zoom_friction;
+   if ((wd->size.w > 0) && (wd->size.h > 0))
+     {
+       wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.ow;
+       wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.oh;
+     }
+   else
+     {
+       wd->size.spos.x = 0.5;
+       wd->size.spos.y = 0.5;
+     }
+   if (rw > wd->size.ow) wd->size.spos.x = 0.5;
+   if (rh > wd->size.oh) wd->size.spos.y = 0.5;
+   if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0;
+   if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0;
+   if (wd->paused)
+     {
+       zoom_do(obj, 1.0);
+     }
+   else
+     {
+       if (!wd->zoom_animator)
+         {
+            wd->zoom_animator = ecore_animator_add(_zoom_anim, obj);
+            wd->nosmooth++;
+            if (wd->nosmooth == 1) _smooth_update(obj);
+            started = 1;
+         }
+     }
+   if (wd->zoom_animator)
+     {
+       if (!_zoom_anim(obj))
+         {
+            ecore_animator_del(wd->zoom_animator);
+            wd->zoom_animator = NULL;
+         }
+     }
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   if (!wd->paused)
+     {
+       if (started)
+         evas_object_smart_callback_call(obj, SIG_ZOOM_START, NULL);
+       if (!wd->zoom_animator)
+         evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
+     }
+
+   if (zoom_changed)
+     evas_object_smart_callback_call(obj, SIG_ZOOM_CHANGE, NULL);
+}
+
+/**
+ * Get the zoom level of the photo
+ *
+ * This returns the current zoom level of the map object. Note that if
+ * you set the fill mode to other than ELM_MAP_ZOOM_MODE_MANUAL
+ * (which is the default), the zoom level may be changed at any time by the
+ * map object itself to account for map size and map viewpoer size
+ *
+ * @param obj The map object
+ * @return The current zoom level
+ *
+ * @ingroup Map
+ */
+EAPI double
+elm_map_zoom_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 1.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 1.0;
+   return wd->zoom;
+}
+
+/**
+ * Set the zoom mode
+ *
+ * This sets the zoom mode to manual or one of several automatic levels.
+ * Manual (ELM_MAP_ZOOM_MODE_MANUAL) means that zoom is set manually by
+ * elm_map_zoom_set() and will stay at that level until changed by code
+ * or until zoom mode is changed. This is the default mode.
+ * The Automatic modes will allow the map object to automatically
+ * adjust zoom mode based on properties. ELM_MAP_ZOOM_MODE_AUTO_FIT) will
+ * adjust zoom so the photo fits inside the scroll frame with no pixels
+ * outside this area. ELM_MAP_ZOOM_MODE_AUTO_FILL will be similar but
+ * ensure no pixels within the frame are left unfilled. Do not forget that the valid sizes are 2^zoom, consequently the map may be smaller than the scroller view.
+ *
+ * @param obj The map object
+ * @param mode The desired mode
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_Mode mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->mode == mode) return;
+   wd->mode = mode;
+     {
+       double tz = wd->zoom;
+       wd->zoom = 0.0;
+       elm_map_zoom_set(wd->obj, tz);
+     }
+}
+
+/**
+ * Get the zoom mode
+ *
+ * This gets the current zoom mode of the map object
+ *
+ * @param obj The map object
+ * @return The current zoom mode
+ *
+ * @ingroup Map
+ */
+EAPI Elm_Map_Zoom_Mode
+elm_map_zoom_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ZOOM_MODE_MANUAL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_MAP_ZOOM_MODE_MANUAL;
+   return wd->mode;
+}
+
+/**
+ * Centers the map at @p lon @p lat using an animation to scroll.
+ *
+ * @param obj The map object
+ * @param lon Longitude to center at
+ * @param lon Latitude to center at
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_geo_region_bring_in(Evas_Object *obj, double lon, double lat)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int rx, ry, rw, rh;
+
+   if (!wd) return;
+   elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+
+   rx = rx - rw / 2;
+   ry = ry - rh / 2;
+
+   if (wd->zoom_animator)
+     {
+       wd->nosmooth--;
+       if (!wd->nosmooth) _smooth_update(obj);
+       ecore_animator_del(wd->zoom_animator);
+       wd->zoom_animator = NULL;
+       zoom_do(obj, 1.0);
+       evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
+     }
+   elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh);
+
+   wd->center_on.enabled = EINA_TRUE;
+   wd->center_on.lon = lon;
+   wd->center_on.lat = lat;
+}
+
+/**
+ * Move the map to the current coordinates.
+ *
+ * This move the map to the current coordinates. The map will be centered on these coordinates.
+ *
+ * @param obj The map object
+ * @param lat The latitude.
+ * @param lon The longitude.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_geo_region_show(Evas_Object *obj, double lon, double lat)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int rx, ry, rw, rh;
+
+   if (!wd) return;
+   elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+
+   rx = rx - rw / 2;
+   ry = ry - rh / 2;
+
+   if (wd->zoom_animator)
+     {
+       wd->nosmooth--;
+       ecore_animator_del(wd->zoom_animator);
+       wd->zoom_animator = NULL;
+       zoom_do(obj, 1.0);
+       evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
+     }
+   elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh);
+
+   wd->center_on.enabled = EINA_TRUE;
+   wd->center_on.lon = lon;
+   wd->center_on.lat = lat;
+}
+
+/**
+ * Get the current coordinates of the map.
+ *
+ * This gets the current coordinates of the map object.
+ *
+ * @param obj The map object
+ * @param lat The latitude.
+ * @param lon The longitude.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_geo_region_get(const Evas_Object *obj, double *lon, double *lat)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord sx, sy, sw, sh;
+
+   if (!wd) return;
+   elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
+   sx += sw / 2;
+   sy += sh / 2;
+
+   elm_map_utils_convert_coord_into_geo(obj, sx, sy, wd->size.w, lon, lat);
+}
+
+/**
+ * Set the paused state for map
+ *
+ * This sets the paused state to on (1) or off (0) for map. The default
+ * is off. This will stop zooming using animation change zoom levels and
+ * change instantly. This will stop any existing animations that are running.
+ *
+ * @param obj The map object
+ * @param paused The pause state to set
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_paused_set(Evas_Object *obj, Eina_Bool paused)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->paused == !!paused) return;
+   wd->paused = paused;
+   if (wd->paused)
+     {
+       if (wd->zoom_animator)
+         {
+            ecore_animator_del(wd->zoom_animator);
+            wd->zoom_animator = NULL;
+            zoom_do(obj, 1.0);
+            evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
+         }
+     }
+}
+
+/**
+ * Set the paused state for the markers
+ *
+ * This sets the paused state to on (1) or off (0) for the markers. The default
+ * is off. This will stop displaying the markers during change zoom levels. Set
+ * to on if you have a large number of markers.
+ *
+ * @param obj The map object
+ * @param paused The pause state to set
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_paused_markers_set(Evas_Object *obj, Eina_Bool paused)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->paused_markers == !!paused) return;
+   wd->paused_markers = paused;
+}
+
+/**
+ * Get the paused state for map
+ *
+ * This gets the current paused state for the map object.
+ *
+ * @param obj The map object
+ * @return The current paused state
+ *
+ * @ingroup Map
+ */
+EAPI Eina_Bool
+elm_map_paused_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->paused;
+}
+
+/**
+ * Get the paused state for the markers
+ *
+ * This gets the current paused state for the markers object.
+ *
+ * @param obj The map object
+ * @return The current paused state
+ *
+ * @ingroup Map
+ */
+EAPI Eina_Bool
+elm_map_paused_markers_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->paused_markers;
+}
+
+/**
+ * Get the information of downloading status
+ *
+ * This gets the current downloading status for the map object.
+ *
+ * @param obj The map object
+ * @param try_num the number of download trying map
+ * @param finish_num the number of downloaded map
+ *
+ * @ingroup Map
+ */
+
+EAPI void 
+elm_map_utils_downloading_status_get(const Evas_Object *obj, int *try_num, int *finish_num)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (try_num)
+     {
+        *try_num = wd->try_num;
+     }
+
+   if (finish_num)
+     {
+        *finish_num = wd->finish_num;
+     }
+}
+/**
+ * Convert a pixel coordinate (x,y) into a geographic coordinate (longitude, latitude).
+ *
+ * @param obj The map object
+ * @param x the coordinate
+ * @param y the coordinate
+ * @param size the size in pixels of the map. The map is a square and generally his size is : pow(2.0, zoom)*256.
+ * @param lon the longitude correspond to x
+ * @param lat the latitude correspond to y
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int size, double *lon, double *lat)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int zoom = floor(log2(size/256));
+
+   if (elm_map_source_get(obj) == ELM_MAP_SOURCE_MODULE)
+     if ((wd->api) && (wd->api->obj_convert_coord_into_geo))
+       if (wd->api->obj_convert_coord_into_geo(obj, zoom, x, y, size, lon, lat)) return;
+
+   if (lon)
+     {
+       *lon = x / (double)size * 360.0 - 180;
+     }
+   if (lat)
+     {
+       double n = ELM_PI - 2.0 * ELM_PI * y / size;
+       *lat = 180.0 / ELM_PI * atan(0.5 * (exp(n) - exp(-n)));
+     }
+}
+
+/**
+ * Convert a geographic coordinate (longitude, latitude) into a pixel coordinate (x, y).
+ *
+ * @param obj The map object
+ * @param lon the longitude
+ * @param lat the latitude
+ * @param size the size in pixels of the map. The map is a square and generally his size is : pow(2.0, zoom)*256.
+ * @param x the coordinate correspond to the longitude
+ * @param y the coordinate correspond to the latitude
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double lat, int size, int *x, int *y)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int zoom = floor(log2(size/256));
+
+   if (elm_map_source_get(obj) == ELM_MAP_SOURCE_MODULE)
+     if ((wd->api) && (wd->api->obj_convert_geo_into_coord))
+       if (wd->api->obj_convert_geo_into_coord(obj, zoom, lon, lat, size, x, y)) return;
+
+   if (x)
+     *x = floor((lon + 180.0) / 360.0 * size);
+   if (y)
+     *y = floor((1.0 - log( tan(lat * ELM_PI/180.0) + 1.0 / cos(lat * ELM_PI/180.0)) / ELM_PI) / 2.0 * size);
+}
+
+
+
+/**
+ * Add a marker on the map
+ *
+ * @param obj The map object
+ * @param lon the longitude
+ * @param lat the latitude
+ * @param clas the class to use
+ * @param data the data passed to the callbacks
+ *
+ * @return The marker object
+ *
+ * @ingroup Map
+ */
+EAPI Elm_Map_Marker *
+elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *clas_group, void *data)
+{
+   int i, j;
+   Eina_List *l;
+   Marker_Group *group;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int mpi, mpj;
+   int tabi[9];
+   int tabj[9];
+   const char *s;
+   const char *style;
+   Evas_Object *o;
+
+   if (!wd) return NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(clas_group, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(clas, NULL);
+
+   Elm_Map_Marker *marker = ELM_NEW(Elm_Map_Marker);
+
+   marker->wd = wd;
+   marker->clas = clas;
+   marker->clas_group = clas_group;
+   marker->longitude = lon;
+   marker->latitude = lat;
+   marker->data = data;
+
+   tabi[1] = tabi[4] = tabi[6] = -1;
+   tabi[2] = tabi[0] = tabi[7] = 0;
+   tabi[3] = tabi[5] = tabi[8] = 1;
+
+   tabj[1] = tabj[2] = tabj[3] = -1;
+   tabj[4] = tabj[0] = tabj[5] = 0;
+   tabj[6] = tabj[7] = tabj[8] = 1;
+
+   if (!clas_group->priv.set)
+     {
+       style = "radio";
+       if (marker->clas_group && marker->clas_group->style)
+         style = marker->clas_group->style;
+
+       o = edje_object_add(evas_object_evas_get(obj));
+       _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj));
+       s = edje_object_data_get(o, "size_w");
+       clas_group->priv.edje_w = atoi(s);
+       s = edje_object_data_get(o, "size_h");
+       clas_group->priv.edje_h = atoi(s);
+       s = edje_object_data_get(o, "size_max_w");
+       clas_group->priv.edje_max_w = atoi(s);
+       s = edje_object_data_get(o, "size_max_h");
+       clas_group->priv.edje_max_h = atoi(s);
+       evas_object_del(o);
+
+       clas_group->priv.set = EINA_TRUE;
+     }
+
+   if (!clas->priv.set)
+     {
+       style = "radio";
+       if (marker->clas && marker->clas->style)
+         style = marker->clas->style;
+        
+       o = edje_object_add(evas_object_evas_get(obj));
+       _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj));
+       s = edje_object_data_get(o, "size_w");
+       clas->priv.edje_w = atoi(s);
+       s = edje_object_data_get(o, "size_h");
+       clas->priv.edje_h = atoi(s);
+       evas_object_del(o);
+
+       clas->priv.set = EINA_TRUE;
+     }
+
+   for (i = clas_group->zoom_displayed; i <= ZOOM_MAX; i++)
+     {
+       elm_map_utils_convert_geo_into_coord(obj, lon, lat, pow(2.0, i)*wd->tsize,
+                                             &(marker->x[i]), &(marker->y[i]));
+        
+       //search in the matrixsparse the region where the marker will be
+       mpi = marker->x[i] / wd->tsize;
+       mpj = marker->y[i] / wd->tsize;
+
+       if (!wd->markers[i])
+         {
+            int size =  pow(2.0, i);
+            wd->markers[i] = eina_matrixsparse_new(size, size, NULL, NULL);
+         }
+
+       group = NULL;
+       if (i <= clas_group->zoom_grouped)
+         {
+            for (j = 0, group = NULL; j < 9 && !group; j++)
+              {
+                 EINA_LIST_FOREACH(eina_matrixsparse_data_idx_get(wd->markers[i], mpj + tabj[j], mpi + tabi[j]),
+                                    l, group)
+                   {
+                      if (group->clas == marker->clas_group
+                           && ELM_RECTS_INTERSECT(marker->x[i]-clas->priv.edje_w/4,
+                                                  marker->y[i]-clas->priv.edje_h/4, clas->priv.edje_w, clas->priv.edje_h,
+                                                  group->x-group->w/4, group->y-group->h/4, group->w, group->h))
+                        {
+                           group->markers = eina_list_append(group->markers, marker);
+                           group->update_nbelems = EINA_TRUE;
+                           group->update_resize = EINA_TRUE;
+
+                           group->sum_x += marker->x[i];
+                           group->sum_y += marker->y[i];
+                           group->x = group->sum_x / eina_list_count(group->markers);
+                           group->y = group->sum_y / eina_list_count(group->markers);
+
+                           group->w = group->clas->priv.edje_w + group->clas->priv.edje_w/8.
+                              * eina_list_count(group->markers);
+                           group->h = group->clas->priv.edje_h + group->clas->priv.edje_h/8.
+                              * eina_list_count(group->markers);
+                           if (group->w > group->clas->priv.edje_max_w) group->w = group->clas->priv.edje_max_w;
+                           if (group->h > group->clas->priv.edje_max_h) group->h = group->clas->priv.edje_max_h;
+
+                           if (group->obj && eina_list_count(group->markers) == 2)
+                             {
+                                _group_object_free(group);
+                                _group_object_create(group);
+                             }
+                           if (group->bubble)
+                             _group_bubble_content_update(group);
+                            
+                           break;
+                        }
+                   }
+              }
+         }
+       if (!group)
+         {
+            group = calloc(1, sizeof(Marker_Group));
+            group->wd = wd;
+            group->sum_x = marker->x[i];
+            group->sum_y = marker->y[i];
+            group->x = marker->x[i];
+            group->y = marker->y[i];
+            group->w = clas_group->priv.edje_w;
+            group->h = clas_group->priv.edje_h;
+            group->clas = clas_group;
+
+            group->markers = eina_list_append(group->markers, marker);
+            group->update_nbelems = EINA_TRUE;
+            group->update_resize = EINA_TRUE;
+
+            eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell));
+
+            if (!group->cell)
+              {
+                 l = eina_list_append(NULL, group);
+                 eina_matrixsparse_data_idx_set(wd->markers[i], mpj, mpi, l);
+                 eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell));
+              }
+            else
+              {
+                 l = eina_matrixsparse_cell_data_get(group->cell);
+                 l = eina_list_append(l, group);
+                 eina_matrixsparse_cell_data_set(group->cell, l);
+              }
+         }
+       marker->groups[i] = group;
+     }
+
+   if (wd->grids)
+     {
+       Evas_Coord ox, oy, ow, oh;
+       evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
+       marker_place(obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
+     }
+
+   return marker;
+}
+
+/**
+ * Remove a marker from the map
+ *
+ * @param marker The marker to remove
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_remove(Elm_Map_Marker *marker)
+{
+   int i;
+   Eina_List *groups;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN(marker);
+   wd = marker->wd;
+   if (!wd) return;
+   for (i = 0; i <= ZOOM_MAX; i++)
+     {
+       marker->groups[i]->markers = eina_list_remove(marker->groups[i]->markers, marker);
+       if (!eina_list_count(marker->groups[i]->markers))
+         {
+             groups = eina_matrixsparse_cell_data_get(marker->groups[i]->cell);
+             groups = eina_list_remove(groups, marker->groups[i]);
+             eina_matrixsparse_cell_data_set(marker->groups[i]->cell, groups);
+             
+             _group_object_free(marker->groups[i]);
+             _group_bubble_free(marker->groups[i]);
+             free(marker->groups[i]);
+         }
+       else
+         {
+            marker->groups[i]->sum_x -= marker->x[i];
+            marker->groups[i]->sum_y -= marker->y[i];
+             
+            marker->groups[i]->x = marker->groups[i]->sum_x / eina_list_count(marker->groups[i]->markers);
+            marker->groups[i]->y = marker->groups[i]->sum_y / eina_list_count(marker->groups[i]->markers);
+             
+            marker->groups[i]->w = marker->groups[i]->clas->priv.edje_w
+               + marker->groups[i]->clas->priv.edje_w/8. * eina_list_count(marker->groups[i]->markers);
+            marker->groups[i]->h = marker->groups[i]->clas->priv.edje_h
+               + marker->groups[i]->clas->priv.edje_h/8. * eina_list_count(marker->groups[i]->markers);
+            if (marker->groups[i]->w > marker->groups[i]->clas->priv.edje_max_w)
+              marker->groups[i]->w = marker->groups[i]->clas->priv.edje_max_w;
+            if (marker->groups[i]->h > marker->groups[i]->clas->priv.edje_max_h)
+              marker->groups[i]->h = marker->groups[i]->clas->priv.edje_max_h;
+         }
+       if ((marker->groups[i]->obj) && (eina_list_count(marker->groups[i]->markers) == 1))
+         {
+            _group_object_free(marker->groups[i]);
+            _group_object_create(marker->groups[i]);
+         }
+     }
+
+   if ((marker->content) && (marker->clas->func.del))
+     marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content);
+   else if (marker->content)
+     evas_object_del(marker->content);
+   
+   free(marker);
+   
+   if (wd->grids)
+     {
+       Evas_Coord ox, oy, ow, oh;
+       evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
+       marker_place(wd->obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
+     }
+}
+
+/**
+ * Move the map to the coordinate of the marker.
+ *
+ * @param marker The marker where the map will be center.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_bring_in(Elm_Map_Marker *marker)
+{
+   EINA_SAFETY_ON_NULL_RETURN(marker);
+   elm_map_geo_region_bring_in(marker->wd->obj, marker->longitude, marker->latitude);
+}
+
+
+/**
+ * Move the map to the coordinate of the marker.
+ *
+ * @param marker The marker where the map will be center.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_show(Elm_Map_Marker *marker)
+{
+   EINA_SAFETY_ON_NULL_RETURN(marker);
+   elm_map_geo_region_show(marker->wd->obj, marker->longitude, marker->latitude);
+}
+
+/**
+ * Move and zoom the map to display a list of markers.
+ *
+ * The map will be centered on the center point of the markers in the list. Then
+ * the map will be zoomed in order to fit the markers using the maximum zoom which
+ * allows display of all the markers.
+ *
+ * @param markers The list of markers (list of Elm_Map_Marker *)
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_markers_list_show(Eina_List *markers)
+{
+   int zoom;
+   double lon, lat;
+   Eina_List *l;
+   Elm_Map_Marker *marker, *m_max_lon = NULL, *m_max_lat = NULL, *m_min_lon = NULL, *m_min_lat = NULL;
+   Evas_Coord rw, rh, xc, yc;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN(markers);
+
+   EINA_LIST_FOREACH(markers, l, marker)
+     {
+       wd = marker->wd;
+
+       if ((!m_min_lon) || (marker->longitude < m_min_lon->longitude))
+         m_min_lon = marker;
+        
+       if ((!m_max_lon) || (marker->longitude > m_max_lon->longitude))
+         m_max_lon = marker;
+        
+       if ((!m_min_lat) || (marker->latitude > m_min_lat->latitude))
+         m_min_lat = marker;
+        
+       if ((!m_max_lat) || (marker->latitude < m_max_lat->latitude))
+         m_max_lat = marker;
+     }
+   
+   lon = (m_max_lon->longitude - m_min_lon->longitude) / 2. + m_min_lon->longitude;
+   lat = (m_max_lat->latitude - m_min_lat->latitude) / 2. + m_min_lat->latitude;
+   
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+   for (zoom = map_sources_tab[wd->source].zoom_max; zoom>map_sources_tab[wd->source].zoom_min; zoom--)
+     {
+       Evas_Coord size = pow(2.0, zoom)*wd->tsize;
+       elm_map_utils_convert_geo_into_coord(wd->obj, lon, lat, size, &xc, &yc);
+        
+       if ((m_min_lon->x[zoom] - wd->marker_max_w >= xc-rw/2)
+            && (m_min_lat->y[zoom] - wd->marker_max_h >= yc-rh/2)
+            && (m_max_lon->x[zoom] + wd->marker_max_w <= xc+rw/2)
+            && (m_max_lat->y[zoom] + wd->marker_max_h <= yc+rh/2))
+         break;
+     }
+
+   elm_map_geo_region_show(wd->obj, lon, lat);
+   elm_map_zoom_set(wd->obj, zoom);
+}
+
+/**
+ * Set the maximum numbers of markers display in a group.
+ *
+ * A group can have a long list of markers, consequently the creation of the content
+ * of the bubble can be very slow. In order to avoid this, a maximum number of items
+ * is displayed in a bubble. By default this number is 30.
+ *
+ * @param obj The map object.
+ * @param max The maximum numbers of items displayed in a bubble.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_max_marker_per_group_set(Evas_Object *obj, int max)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->markers_max_num = max;
+}
+
+/**
+ * Return the evas object getting from the ElmMapMarkerGetFunc callback
+ *
+ * @param marker The marker.
+ * @return Return the evas object if it exists, else NULL.
+ *
+ * @ingroup Map
+ */
+EAPI Evas_Object *
+elm_map_marker_object_get(const Elm_Map_Marker *marker)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(marker, NULL);
+   return marker->content;
+}
+
+/**
+ * Update the marker
+ *
+ * @param marker The marker.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_update(Elm_Map_Marker *marker)
+{
+   EINA_SAFETY_ON_NULL_RETURN(marker);
+   if (marker->content)
+     {
+       if (marker->clas->func.del)
+         marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content);
+       else
+         evas_object_del(marker->content);
+       marker->content = NULL;
+       _group_bubble_content_update(marker->groups[marker->wd->zoom]);
+     }
+}
+
+/**
+ * Close all opened bubbles
+ *
+ * @param obj The map object
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_bubbles_close(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Marker_Group *group;
+   Eina_List *l, *l_next;
+   if (!wd) return;
+   EINA_LIST_FOREACH_SAFE(wd->opened_bubbles, l, l_next, group)
+     _group_bubble_free(group);
+}
+
+
+/**
+ * Create a group class.
+ *
+ * Each marker must be associated to a group class. Marker with the same group are grouped if they are close.
+ * The group class defines the style of the marker when a marker is grouped to others markers.
+ *
+ * @param obj The map object
+ * @return Returns the new group class
+ *
+ * @ingroup Map
+ */
+EAPI Elm_Map_Group_Class *
+elm_map_group_class_new(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   Elm_Map_Group_Class *clas = calloc(1, sizeof(Elm_Map_Group_Class));
+   clas->zoom_grouped = ZOOM_MAX;
+   wd->groups_clas = eina_list_append(wd->groups_clas, clas);
+   return clas;
+}
+
+/**
+ * Set the style of a group class (radio, radio2 or empty)
+ *
+ * @param clas the group class
+ * @param style the new style
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_group_class_style_set(Elm_Map_Group_Class *clas, const char *style)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   eina_stringshare_replace(&clas->style, style);
+}
+
+/**
+ * Set the icon callback of a group class.
+ *
+ * A custom icon can be displayed in a marker. The function @ref icon_get must return this icon.
+ *
+ * @param clas the group class
+ * @param icon_get the callback to create the icon
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, ElmMapGroupIconGetFunc icon_get)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   clas->func.icon_get = icon_get;
+}
+
+/**
+ * Set the data associated to the group class (radio, radio2 or empty)
+ *
+ * @param clas the group class
+ * @param data the new user data
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_group_class_data_set(Elm_Map_Group_Class *clas, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   clas->data = data;
+}
+
+/**
+ * Set the zoom from where the markers are displayed.
+ *
+ * Markers will not be displayed for a zoom less than @ref zoom
+ *
+ * @param clas the group class
+ * @param zoom the zoom
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_group_class_zoom_displayed_set(Elm_Map_Group_Class *clas, int zoom)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   clas->zoom_displayed = zoom;
+}
+
+/**
+ * Set the zoom from where the markers are no more grouped.
+ *
+ * @param clas the group class
+ * @param zoom the zoom
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_group_class_zoom_grouped_set(Elm_Map_Group_Class *clas, int zoom)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   clas->zoom_grouped = zoom;
+}
+
+/**
+ * Set if the markers associated to the group class @clas are hidden or not.
+ * If @ref hide is true the markers will be hidden.
+ *
+ * @param clas the group class
+ * @param hide if true the markers will be hidden, else they will be displayed.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_group_class_hide_set(Evas_Object *obj, Elm_Map_Group_Class *clas, Eina_Bool hide)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   if (clas->hide == hide) return;
+   clas->hide = hide;
+   if (wd->grids)
+     {
+       Evas_Coord ox, oy, ow, oh;
+       evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
+       marker_place(obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
+     }
+}
+
+
+/**
+ * Create a marker class.
+ *
+ * Each marker must be associated to a class.
+ * The class defines the style of the marker when a marker is displayed alone (not grouped).
+ *
+ * @param obj The map object
+ * @return Returns the new class
+ *
+ * @ingroup Map
+ */
+EAPI Elm_Map_Marker_Class *
+elm_map_marker_class_new(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   Elm_Map_Marker_Class *clas = calloc(1, sizeof(Elm_Map_Marker_Class));
+   wd->markers_clas = eina_list_append(wd->markers_clas, clas);
+   return clas;
+}
+
+/**
+ * Set the style of a class (radio, radio2 or empty)
+ *
+ * @param clas the group class
+ * @param style the new style
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_class_style_set(Elm_Map_Marker_Class *clas, const char *style)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   eina_stringshare_replace(&clas->style, style);
+}
+
+/**
+ * Set the icon callback of a class.
+ *
+ * A custom icon can be displayed in a marker. The function @ref icon_get must return this icon.
+ *
+ * @param clas the group class
+ * @param icon_get the callback to create the icon
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerIconGetFunc icon_get)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   clas->func.icon_get = icon_get;
+}
+
+/**
+ *
+ * Set the callback of the content of the bubble.
+ *
+ * When the user click on a marker, a bubble is displayed with a content.
+ * The callback @ref get musst return this content. It can be NULL.
+ *
+ * @param clas the group class
+ * @param get the callback to create the content
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerGetFunc get)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   clas->func.get = get;
+}
+
+/**
+ * Set the callback of the content of delete the object created by the callback "get".
+ *
+ * If this callback is defined the user will have to delete (or not) the object inside.
+ * If the callback is not defined the object will be destroyed with evas_object_del()
+ *
+ * @param clas the group class
+ * @param del the callback to delete the content
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerDelFunc del)
+{
+   EINA_SAFETY_ON_NULL_RETURN(clas);
+   clas->func.del = del;
+}
+
+/**
+ * Set the source of the map.
+ *
+ * Elm_Map retrieves the image which composed the map from a web service. This web service can
+ * be set with this method. A different service can return a different maps with different
+ * information and it can use different zoom value.
+ *
+ * @param clas the group class
+ * @param source the new source
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_source_set(Evas_Object *obj, Elm_Map_Sources source)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Grid *grid;
+   int zoom;
+   if (!wd) return;
+   if (wd->source == source ) return;
+   if (!map_sources_tab[source].url_cb) return;
+
+   EINA_LIST_FREE(wd->grids, grid) grid_clear(obj, grid);
+
+   wd->source = source;
+   zoom = wd->zoom;
+   wd->zoom = -1;
+   
+   if (map_sources_tab[wd->source].zoom_max < zoom)
+     zoom = map_sources_tab[wd->source].zoom_max;
+   if (map_sources_tab[wd->source].zoom_min > zoom)
+     zoom = map_sources_tab[wd->source].zoom_min;
+   
+   elm_map_zoom_set(obj, zoom);
+}
+
+/**
+ * Get the current source
+ *
+ * @param obj the map object
+ * @return Returns the maximum zoom of the source
+ *
+ * @ingroup Map
+ */
+EAPI Elm_Map_Sources
+elm_map_source_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_SOURCE_MAPNIK;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_MAP_SOURCE_MAPNIK;
+   return wd->source;
+}
+
+/**
+ * Set the API of a custom source.
+ *
+ * A custom web service can be associated to the source ELM_MAP_SOURCE_CUSTOM_(1..7).
+ *
+ * @param source the source ID (ELM_MAP_SOURCE_CUSTOM_(1..7))
+ * @param name the name of the source
+ * @param zoom_min the minimum zoom of the source, must be >= 0
+ * @param zoom_max the maximum zoom of the source, must be <= ZOOM_MAX
+ * @param url_cb the callback used to create the url from where a tile (png or jpeg file) is downloaded.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_source_custom_api_set(Elm_Map_Sources source, const char *name, int zoom_min, int zoom_max, ElmMapSourceURLFunc url_cb)
+{
+   EINA_SAFETY_ON_NULL_RETURN(name);
+   EINA_SAFETY_ON_NULL_RETURN(url_cb);
+   map_sources_tab[source].name = name;
+   map_sources_tab[source].zoom_min = zoom_min;
+   map_sources_tab[source].zoom_max = zoom_max;
+   map_sources_tab[source].url_cb = url_cb;
+}
+
+/**
+ * Get the maximum zoom of the source.
+ *
+ * @param source the source
+ * @return Returns the maximum zoom of the source
+ *
+ * @ingroup Map
+ */
+EAPI int
+elm_map_source_zoom_max_get(Elm_Map_Sources source)
+{
+   return map_sources_tab[source].zoom_max;
+}
+
+/**
+ * Get the minimum zoom of the source.
+ *
+ * @param source the source
+ * @return Returns the minimum zoom of the source
+ *
+ * @ingroup Map
+ */
+EAPI int
+elm_map_source_zoom_min_get(Elm_Map_Sources source)
+{
+   return map_sources_tab[source].zoom_min;
+}
+
+/**
+ * Get the name of a source.
+ *
+ * @param source the source
+ * @return Returns the name of the source
+ *
+ * @ingroup Map
+ */
+EAPI const char *
+elm_map_source_name_get(Elm_Map_Sources source)
+{
+   return map_sources_tab[source].name;
+}
+
+
+static char *
+_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "http://tile.openstreetmap.org/%d/%d/%d.png",
+            zoom, x, y);
+   return strdup(buf);
+}
+
+static char *
+_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), 
+            "http://tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png",
+            zoom, x, y);
+   return strdup(buf);
+}
+
+static char *
+_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), 
+            "http://andy.sandbox.cloudmade.com/tiles/cycle/%d/%d/%d.png",
+            zoom, x, y);
+   return strdup(buf);
+}
+
+static char *
+_maplint_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), 
+            "http://tah.openstreetmap.org/Tiles/maplint/%d/%d/%d.png",
+            zoom, x, y);
+   return strdup(buf);
+}
+
+static char *
+_custom1_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
+{
+   return strdup("");
+}
+
+static char *
+_custom2_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
+{
+   return strdup("");
+}
+
+static char *
+_custom3_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
+{
+   return strdup("");
+}
+
+static char *
+_custom4_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
+{
+   return strdup("");
+}
+
+static char *
+_custom5_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
+{
+   return strdup("");
+}
+
+static char *
+_custom6_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
+{
+   return strdup("");
+}
+
+static char *
+_module_url_cb(Evas_Object *obj, int x, int y, int zoom)
+{
+   char *buf = NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (elm_map_source_get(obj) == ELM_MAP_SOURCE_MODULE)
+      if ((wd->api) && (wd->api->obj_url_request))
+         buf = wd->api->obj_url_request(obj, x, y, zoom);
+
+   if (!buf) buf = strdup("");
+
+   return buf;
+}
+
diff --git a/src/lib/elm_mapbuf.c b/src/lib/elm_mapbuf.c
new file mode 100644 (file)
index 0000000..fc4d6ac
--- /dev/null
@@ -0,0 +1,395 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Mapbuf Mapbuf
+ *
+ * This holds 1 content object and uses an Evas Map to move/resize etc. it.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *content, *clip;
+   Eina_Bool enabled : 1;
+   Eina_Bool alpha : 1;
+   Eina_Bool smooth : 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 _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;
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _sizing_eval(obj);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   Evas_Coord maxw = -1, maxh = -1;
+   if (!wd) return;
+   if (wd->content)
+     {
+        evas_object_size_hint_min_get(wd->content, &minw, &minh);
+        evas_object_size_hint_max_get(wd->content, &maxw, &maxh);
+     }
+   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;
+   if (sub == wd->content)
+     {
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       wd->content = NULL;
+       _sizing_eval(obj);
+     }
+}
+
+static void
+_mapbuf(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord x, y, w, h;
+   if (!wd) return;
+   evas_object_geometry_get(wd->clip, &x, &y, &w, &h);
+   if (wd->enabled)
+     {
+        Evas_Map *m;
+
+        m = evas_map_new(4);
+        evas_map_util_points_populate_from_geometry(m, x, y, w, h, 0);
+        evas_map_smooth_set(m, wd->smooth);
+        evas_map_alpha_set(m, wd->alpha);
+        evas_object_map_set(wd->content, m);
+        evas_object_map_enable_set(wd->content, wd->enabled);
+        evas_map_free(m);
+     }
+   else
+     {
+        evas_object_map_set(wd->content, NULL);
+        evas_object_map_enable_set(wd->content, 0);
+        evas_object_move(wd->content, x, y);
+        evas_object_resize(wd->content, w, h);
+     }
+}
+
+static void
+_configure(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content)
+     {
+        Evas_Coord x, y, w, h, x2, y2;
+
+        evas_object_geometry_get(wd->clip, &x, &y, &w, &h);
+        evas_object_geometry_get(wd->content, &x2, &y2, NULL, NULL);
+        if ((x != x2) || (y != y2))
+          {
+             if (!wd->enabled)
+                evas_object_move(wd->content, x, y);
+             else
+               {
+                  
+                  Evas *e = evas_object_evas_get(obj);
+                  evas_smart_objects_calculate(e);
+                  evas_nochange_push(e);
+//                  printf("x-------------------- %i %i\n", x, y);
+                  evas_object_move(wd->content, x, y);
+                  evas_smart_objects_calculate(e);
+//                  printf("y--------------------\n");
+                  evas_nochange_pop(e);
+               }
+          }
+        evas_object_resize(wd->content, w, h);
+        _mapbuf(obj);
+     }
+}
+
+static void
+_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _configure(data);
+}
+
+static void
+_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{    
+   _configure(data);
+}
+
+/**
+ * Add a new mapbuf to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Mapbuf
+ */
+EAPI Evas_Object *
+elm_mapbuf_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "mapbuf");
+   elm_widget_type_set(obj, "mapbuf");
+   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, EINA_FALSE);
+
+   wd->clip = evas_object_rectangle_add(e);
+   evas_object_static_clip_set(wd->clip, EINA_TRUE);
+   evas_object_pass_events_set(wd->clip, EINA_TRUE);
+   evas_object_color_set(wd->clip, 0, 0, 0, 0);
+
+   evas_object_event_callback_add(wd->clip, EVAS_CALLBACK_MOVE, _move, obj);
+   evas_object_event_callback_add(wd->clip, EVAS_CALLBACK_RESIZE, _resize, obj);
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+  
+   elm_widget_resize_object_set(obj, wd->clip);
+   
+   wd->enabled = 0;
+   wd->alpha = 1;
+   wd->smooth = 1;
+   
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the mapbuf front content
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_mapbuf_content_unset() function.
+ *
+ * @param obj The mapbuf object
+ * @param content The content will be filled in this mapbuf object
+ *
+ * @ingroup Mapbuf
+ */
+EAPI void
+elm_mapbuf_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content) evas_object_del(wd->content);
+   wd->content = content;
+   if (content)
+     {
+        evas_object_data_set(content, "_elm_leaveme", (void *)1);
+       elm_widget_sub_object_add(content, obj);
+       evas_object_smart_member_add(content, obj);
+        evas_object_clip_set(content, wd->clip);
+        evas_object_color_set(wd->clip, 255, 255, 255, 255);
+       evas_object_event_callback_add(content,
+                                       EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+     }
+   else
+     evas_object_color_set(wd->clip, 0, 0, 0, 0);
+   _sizing_eval(obj);
+   _configure(obj);
+}
+
+/**
+ * Get the mapbuf front content
+ *
+ * Return the content object which is set for this widget.
+ *
+ * @param obj The mapbuf object
+ * @return The content that is being used
+ *
+ * @ingroup Mapbuf
+ */
+EAPI Evas_Object *
+elm_mapbuf_content_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->content;
+}
+
+/**
+ * Unset the mapbuf front content
+ *
+ * Unparent and return the content object which was set for this widget.
+ *
+ * @param obj The mapbuf object
+ * @return The content that was being used
+ *
+ * @ingroup Mapbuf
+ */
+EAPI Evas_Object *
+elm_mapbuf_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *content;
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   content = wd->content;
+   elm_widget_sub_object_del(obj, content);
+   evas_object_smart_member_del(content);
+   evas_object_color_set(wd->clip, 0, 0, 0, 0);
+   evas_object_clip_unset(content);
+   evas_object_data_del(content, "_elm_leaveme");
+   wd->content = NULL;
+   return content;
+}
+
+/**
+ * Set the mapbuf enabled state
+ *
+ * @param obj The mapbuf object
+ * @param enabled The value to set the enabled state to
+ *
+ * @ingroup Mapbuf
+ */
+EAPI void
+elm_mapbuf_enabled_set(Evas_Object *obj, Eina_Bool enabled)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->enabled == enabled) return;
+   wd->enabled = enabled;
+   if (wd->content) evas_object_static_clip_set(wd->content, wd->enabled);
+   _configure(obj);
+}
+
+/**
+ * Get the mapbuf enabled state
+ *
+ * @param obj The mapbuf object
+ * @return The value that the enabled state is set to
+ *
+ * @ingroup Mapbuf
+ */
+EAPI Eina_Bool
+elm_mapbuf_enabled_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->enabled;
+}
+
+/**
+ * Sets the mapbuf smooth state
+ *
+ * @param obj The mapbuf object
+ * @param smooth The value of the smooth state of @p obj
+ *
+ * @ingroup Mapbuf
+ */
+EAPI void
+elm_mapbuf_smooth_set(Evas_Object *obj, Eina_Bool smooth)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->smooth == smooth) return;
+   wd->smooth = smooth;
+   _configure(obj);
+}
+
+/**
+ * Gets the mapbuf smooth state
+ *
+ * @param obj The mapbuf object
+ * @return The value of the smooth state of @p obj
+ *
+ * @ingroup Mapbuf
+ */
+EAPI Eina_Bool
+elm_mapbuf_smooth_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->smooth;
+}
+
+/**
+ * Enables/disables the mapbuf alpha channel
+ *
+ * @param obj The mapbuf object
+ * @param alpha The state of the alpha channel
+ *
+ * @ingroup Mapbuf
+ */
+EAPI void
+elm_mapbuf_alpha_set(Evas_Object *obj, Eina_Bool alpha)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->alpha == alpha) return;
+   wd->alpha = alpha;
+   _configure(obj);
+}
+
+/**
+ * Gets the state of the mapbuf alpha channel
+ *
+ * @param obj The mapbuf object
+ * @return The state of the alpha channel
+ *
+ * @ingroup Mapbuf
+ */
+EAPI Eina_Bool
+elm_mapbuf_alpha_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->alpha;
+}
diff --git a/src/lib/elm_menu.c b/src/lib/elm_menu.c
new file mode 100644 (file)
index 0000000..06606ab
--- /dev/null
@@ -0,0 +1,928 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Menu Menu
+ *
+ * A menu is a list of items displayed above the window. Each item can
+ * have a sub-menu. The menu object can be used to display a menu on right
+ * click, in a toolbar, anywhere.
+ *
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Elm_Menu_Item
+{
+   Elm_Widget_Item base;
+   Elm_Menu_Item *parent;
+   Evas_Object *icon;
+   const char *icon_str;
+   const char *label;
+   Evas_Smart_Cb func;
+
+   struct {
+      Evas_Object *hv, *bx, *location;
+      Eina_List *items;
+      Eina_Bool open : 1;
+   } submenu;
+
+   Eina_Bool separator : 1;
+   Eina_Bool disabled : 1;
+};
+
+struct _Widget_Data
+{
+   Evas_Object *hv, *bx, *location, *parent, *obj;
+   Eina_List *items;
+   Evas_Coord xloc, yloc;
+};
+
+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 _submenu_sizing_eval(Elm_Menu_Item *parent);
+static void _item_sizing_eval(Elm_Menu_Item *item);
+static void _submenu_hide(Elm_Menu_Item *item);
+static void _submenu_open(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _parent_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _menu_hide(void *data, Evas_Object *obj, void *event_info);
+
+static void
+_del_item(Elm_Menu_Item *item)
+{
+   Elm_Menu_Item *child;
+
+   elm_widget_item_pre_notify_del(item);
+
+   EINA_LIST_FREE(item->submenu.items, child)
+     _del_item(child);
+
+   if (item->label) eina_stringshare_del(item->label);
+   if (item->submenu.hv) evas_object_del(item->submenu.hv);
+   if (item->submenu.location) evas_object_del(item->submenu.location);
+   if (item->icon_str) eina_stringshare_del(item->icon_str);
+   elm_widget_item_del(item);
+}
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Elm_Menu_Item *item;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj);
+   evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
+
+   EINA_LIST_FREE(wd->items, item)
+     _del_item(item);
+
+   if (wd->hv) evas_object_del(wd->hv);
+   if (wd->location) evas_object_del(wd->location);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Eina_List *l, *_l, *_ll, *ll = NULL;
+   Elm_Menu_Item *item;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   ll = eina_list_append(ll, wd->items);
+   EINA_LIST_FOREACH(ll, _ll, l)
+     {
+       EINA_LIST_FOREACH(l, _l, item)
+         {
+            ll = eina_list_append(ll, item->submenu.items);
+            if (item->separator)
+              _elm_theme_object_set(obj, item->base.view, "menu", "separator",
+                                     elm_widget_style_get(obj));
+            else if (item->submenu.bx)
+              {
+                 _elm_theme_object_set
+                    (obj, item->base.view, "menu", "item_with_submenu",
+                     elm_widget_style_get(obj));
+                 elm_menu_item_label_set(item, item->label);
+                 elm_menu_item_icon_set(item, item->icon_str);
+              }
+            else
+              {
+                 _elm_theme_object_set(obj, item->base.view, "menu", "item",
+                                        elm_widget_style_get(obj));
+                 elm_menu_item_label_set(item, item->label);
+                 elm_menu_item_icon_set(item, item->icon_str);
+              }
+            if (item->disabled)
+              edje_object_signal_emit
+                 (item->base.view, "elm,state,disabled", "elm");
+            else
+              edje_object_signal_emit
+                 (item->base.view, "elm,state,enabled", "elm");
+            edje_object_message_signal_process(item->base.view);
+            edje_object_scale_set(item->base.view, elm_widget_scale_get(obj) *
+                                   _elm_config->scale);
+         }
+     }
+   _sizing_eval(obj);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Eina_List *l;
+   Elm_Menu_Item *item;
+   Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->parent)) return;
+   EINA_LIST_FOREACH(wd->items,l,item) _item_sizing_eval(item);
+   evas_object_geometry_get(wd->location, &x_p, &y_p, &w_p, &h_p);
+   evas_object_geometry_get(wd->parent, &x2, &y2, &w2, &h2);
+   evas_object_geometry_get(wd->bx, &bx, &by, &bw, &bh);
+
+   x_p = wd->xloc;
+   y_p = wd->yloc;
+
+   if (x_p+bw > x2+w2) x_p -= x_p+bw - (x2+w2);
+   if (x_p < x2) x_p += x2 - x_p;
+
+   if (y_p+h_p+bh > y2+h2) y_p -= y_p+h_p+bh - (y2+h2);
+   if (y_p < y2) y_p += y2 - y_p;
+
+   evas_object_move(wd->location, x_p, y_p);
+   evas_object_resize(wd->location, bw, h_p);
+   evas_object_size_hint_min_set(wd->location, bw, h_p);
+   evas_object_size_hint_max_set(wd->location, bw, h_p);
+   elm_hover_target_set(wd->hv, wd->location);
+
+   EINA_LIST_FOREACH(wd->items,l,item)
+     {
+       if (item->submenu.open) _submenu_sizing_eval(item);
+     }
+}
+
+static void
+_submenu_sizing_eval(Elm_Menu_Item *parent)
+{
+   Eina_List *l;
+   Elm_Menu_Item *item;
+   Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh, px, py, pw, ph;
+   Widget_Data *wd = elm_widget_data_get(parent->base.widget);
+   if (!wd) return;
+   EINA_LIST_FOREACH(parent->submenu.items, l, item) _item_sizing_eval(item);
+   evas_object_geometry_get(parent->submenu.location, &x_p, &y_p, &w_p, &h_p);
+   evas_object_geometry_get(parent->base.view, &x2, &y2, &w2, &h2);
+   evas_object_geometry_get(parent->submenu.bx, &bx, &by, &bw, &bh);
+   evas_object_geometry_get(wd->parent, &px, &py, &pw, &ph);
+
+   x_p = x2+w2;
+   y_p = y2;
+
+   if (x_p + bw > px + pw)
+     x_p = x2-bw;
+
+   if (y_p+bh > py+ph)
+     y_p -= y_p+bh - (py+ph);
+   if (y_p < py)
+     y_p += y_p - y_p;
+
+   evas_object_move(parent->submenu.location, x_p, y_p);
+   evas_object_resize(parent->submenu.location, bw, h_p);
+   evas_object_size_hint_min_set(parent->submenu.location, bw, h_p);
+   evas_object_size_hint_max_set(parent->submenu.location, bw, h_p);
+   elm_hover_target_set(parent->submenu.hv, parent->submenu.location);
+
+   EINA_LIST_FOREACH(parent->submenu.items, l, item)
+     {
+       if (item->submenu.open)
+         _submenu_sizing_eval(item);
+     }
+}
+
+static void
+_item_sizing_eval(Elm_Menu_Item *item)
+{
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+   if (!item->separator)
+     elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(item->base.view, &minw, &minh, minw, minh);
+   if (!item->separator)
+     elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_size_hint_min_set(item->base.view, minw, minh);
+   evas_object_size_hint_max_set(item->base.view, maxw, maxh);
+}
+
+static void
+_menu_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = data;
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
+   wd->parent = NULL;
+}
+
+static void
+_item_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Menu_Item *item = data;
+   if (item->submenu.open) _submenu_sizing_eval(item);
+}
+
+static void
+_hover_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   _menu_hide(data, obj, event_info);
+   evas_object_smart_callback_call(data, "clicked", NULL);
+}
+
+static void
+_menu_hide(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Eina_List *l;
+   Elm_Menu_Item *item2;
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_hide(wd->hv);
+   evas_object_hide(data);
+
+   EINA_LIST_FOREACH(wd->items, l, item2)
+     {
+       if (item2->submenu.open) _submenu_hide(item2);
+     }
+}
+
+static void
+_submenu_hide(Elm_Menu_Item *item)
+{
+   Eina_List *l;
+   Elm_Menu_Item *item2;
+   evas_object_hide(item->submenu.hv);
+   item->submenu.open = EINA_FALSE;
+   EINA_LIST_FOREACH(item->submenu.items, l, item2)
+     {
+       if (item2->submenu.open) _submenu_hide(item2);
+     }
+}
+
+static void
+_menu_item_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Elm_Menu_Item *item = data;
+   if (item->submenu.items)
+     {
+       if (!item->submenu.open) _submenu_open(item, NULL, NULL, NULL);
+       else _submenu_hide(item);
+     }
+   else
+     _menu_hide(item->base.widget, NULL, NULL);
+
+   if (item->func) item->func((void *)(item->base.data), item->base.widget, item);
+}
+
+static void
+_menu_item_activate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Eina_List *l;
+   Elm_Menu_Item *item2;
+   Elm_Menu_Item *item = data;
+   if (item->parent)
+     {
+       EINA_LIST_FOREACH(item->parent->submenu.items, l, item2)
+         {
+            if ((item2->submenu.open) && (item2 != item)) _submenu_hide(item2);
+         }
+     }
+   else
+     {
+       Widget_Data *wd = elm_widget_data_get(item->base.widget);
+       EINA_LIST_FOREACH(wd->items, l, item2)
+         {
+            if ((item2->submenu.open) && (item2 != item)) _submenu_hide(item2);
+         }
+     }
+}
+
+static void
+_submenu_open(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Elm_Menu_Item *item = data;
+   item->submenu.open = EINA_TRUE;
+   evas_object_show(item->submenu.hv);
+   _sizing_eval(item->base.widget);
+}
+
+static void
+_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_show(wd->hv);
+}
+
+static void
+_item_obj_create(Elm_Menu_Item *item)
+{
+   Widget_Data *wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+   item->base.view = edje_object_add(evas_object_evas_get(wd->bx));
+   evas_object_size_hint_weight_set(item->base.view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(item->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   _elm_theme_object_set(item->base.widget, item->base.view, "menu", "item",  elm_widget_style_get(item->base.widget));
+   edje_object_signal_callback_add(item->base.view, "elm,action,click", "",
+                                   _menu_item_select, item);
+   edje_object_signal_callback_add(item->base.view, "elm,action,activate", "",
+                                   _menu_item_activate, item);
+   evas_object_show(item->base.view);
+}
+
+static void
+_item_separator_obj_create(Elm_Menu_Item *item)
+{
+   Widget_Data *wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+   item->base.view = edje_object_add(evas_object_evas_get(wd->bx));
+   evas_object_size_hint_weight_set(item->base.view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_fill_set(item->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   _elm_theme_object_set(item->base.widget, item->base.view, "menu", "separator",  elm_widget_style_get(item->base.widget));
+   edje_object_signal_callback_add(item->base.view, "elm,action,activate", "",
+                                   _menu_item_activate, item);
+   evas_object_show(item->base.view);
+}
+
+static void
+_item_submenu_obj_create(Elm_Menu_Item *item)
+{
+   Widget_Data *wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+   item->submenu.location = elm_icon_add(wd->bx);
+   item->submenu.hv = elm_hover_add(wd->bx);
+   elm_hover_target_set(item->submenu.hv, item->submenu.location);
+   elm_hover_parent_set(item->submenu.hv, wd->parent);
+   elm_object_style_set(item->submenu.hv, "submenu");
+
+   item->submenu.bx = elm_box_add(wd->bx);
+   evas_object_size_hint_weight_set(item->submenu.bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(item->submenu.bx);
+   elm_hover_content_set(item->submenu.hv, elm_hover_best_content_location_get(item->submenu.hv, ELM_HOVER_AXIS_VERTICAL), item->submenu.bx);
+
+   _elm_theme_object_set(item->base.widget, item->base.view, "menu", "item_with_submenu",  elm_widget_style_get(item->base.widget));
+   elm_menu_item_label_set(item, item->label);
+   elm_menu_item_icon_set(item, item->icon_str);
+
+   edje_object_signal_callback_add(item->base.view, "elm,action,open", "",
+                                   _submenu_open, item);
+   evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOVE, _item_move_resize, item);
+   evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_RESIZE, _item_move_resize, item);
+
+   evas_object_event_callback_add(item->submenu.bx, EVAS_CALLBACK_RESIZE, _menu_resize, item->base.widget);
+}
+
+/**
+ * Add a new menu to the parent
+ *
+ * @param parent The parent object.
+ * @return The new object or NULL if it cannot be created.
+ *
+ * @ingroup Menu
+ */
+EAPI Evas_Object *
+elm_menu_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "menu");
+   elm_widget_type_set(obj, "menu");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   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);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->location = elm_icon_add(obj);
+   wd->parent = parent;
+   wd->obj = obj;
+
+   wd->hv = elm_hover_add(obj);
+   elm_hover_parent_set(wd->hv, parent);
+   elm_hover_target_set(wd->hv, wd->location);
+   elm_object_style_set(wd->hv, "menu");
+   evas_object_smart_callback_add(wd->hv, "clicked", _hover_clicked_cb, obj);
+
+   wd->bx = elm_box_add(obj);
+   evas_object_size_hint_weight_set(wd->bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(wd->bx);
+   elm_hover_content_set(wd->hv, elm_hover_best_content_location_get(wd->hv, ELM_HOVER_AXIS_VERTICAL), wd->bx);
+
+   evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
+   evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
+
+   evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _menu_resize, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the parent
+ *
+ * @param obj The menu object.
+ * @param parent The new parent.
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
+{
+   Eina_List *l, *_l, *_ll, *ll = NULL;
+   Elm_Menu_Item *item;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->parent == parent) return;
+   if (wd->parent)
+     {
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
+     }
+   wd->parent = parent;
+   if (wd->parent)
+     {
+       evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
+       evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
+     }
+   elm_hover_parent_set(wd->hv, parent);
+
+   ll = eina_list_append(ll, wd->items);
+   EINA_LIST_FOREACH(ll, _ll, l)
+     {
+       EINA_LIST_FOREACH(l, _l, item)
+         {
+            if (item->submenu.hv)
+              {
+                 elm_hover_parent_set(item->submenu.hv, parent);
+                 ll = eina_list_append(ll, item->submenu.items);
+              }
+         }
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the parent
+ *
+ * @param obj The menu object.
+ * @return The parent.
+ *
+ * @ingroup Menu
+ */
+EAPI Evas_Object *
+elm_menu_parent_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->parent;
+}
+
+/**
+ * Move the menu to a new position
+ *
+ * @param obj The menu object.
+ * @param x The new position.
+ * @param y The new position.
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->xloc = x;
+   wd->yloc = y;
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the Evas_Object of an Elm_Menu_Item
+ *
+ * @param item The menu item object.
+ *
+ * @ingroup Menu
+ */
+EAPI Evas_Object *
+elm_menu_object_get(const Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->base.view;
+}
+
+static void
+_item_clone(Evas_Object *obj, Elm_Menu_Item *parent, Elm_Menu_Item *item)
+{
+   Elm_Menu_Item *new_item, *subitem;
+   Eina_List *iter;
+
+   if (item->separator)
+      new_item = elm_menu_item_separator_add(obj, parent);
+   else
+      new_item = elm_menu_item_add(obj, parent, item->icon_str, item->label, item->func, item->base.data);
+   elm_menu_item_disabled_set(new_item, item->disabled);
+
+   EINA_LIST_FOREACH(item->submenu.items, iter, subitem)
+      _item_clone(obj, new_item, subitem);
+}
+
+void
+elm_menu_clone(Evas_Object *from_menu, Evas_Object *to_menu, Elm_Menu_Item *parent)
+{
+   ELM_CHECK_WIDTYPE(from_menu, widtype);
+   ELM_CHECK_WIDTYPE(to_menu, widtype);
+   Widget_Data *from_wd = elm_widget_data_get(from_menu);
+   Eina_List *iter;
+   Elm_Menu_Item *item;
+
+   if (!from_wd) return;
+   EINA_LIST_FOREACH(from_wd->items, iter, item)
+      _item_clone(to_menu, parent, item);
+}
+
+/**
+ * Add an item at the end
+ *
+ * @param obj The menu object.
+ * @param icon A icon display on the item. The icon will be destryed by the menu.
+ * @param label The label of the item.
+ * @param func Function called when the user select the item.
+ * @param data Data sent by the callback.
+ * @return Returns the new item.
+ *
+ * @ingroup Menu
+ */
+EAPI Elm_Menu_Item *
+elm_menu_item_add(Evas_Object *obj, Elm_Menu_Item *parent, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   Elm_Menu_Item *subitem;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *icon_obj;
+
+   if (!wd) return NULL;
+   icon_obj = elm_icon_add(obj);
+   if (!icon_obj) return NULL;
+   subitem = elm_widget_item_new(obj, Elm_Menu_Item);
+   if (!subitem)
+     {
+        evas_object_del(icon_obj);
+        return NULL;
+     }
+   subitem->base.data = data;
+   subitem->func = func;
+   subitem->parent = parent;
+   subitem->icon = icon_obj;
+
+   _item_obj_create(subitem);
+   elm_menu_item_label_set(subitem, label);
+
+   elm_widget_sub_object_add(subitem->base.widget, subitem->icon);
+   edje_object_part_swallow(subitem->base.view, "elm.swallow.content", subitem->icon);
+   if (icon) elm_menu_item_icon_set(subitem, icon);
+
+   if (parent)
+     {
+       if (!parent->submenu.bx) _item_submenu_obj_create(parent);
+       elm_box_pack_end(parent->submenu.bx, subitem->base.view);
+       parent->submenu.items = eina_list_append(parent->submenu.items, subitem);
+     }
+   else
+     {
+       elm_box_pack_end(wd->bx, subitem->base.view);
+       wd->items = eina_list_append(wd->items, subitem);
+     }
+
+   _sizing_eval(obj);
+   return subitem;
+}
+
+/**
+ * Set the label of a menu item
+ *
+ * @param item The menu item object.
+ * @param label The label to set for @p item
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_item_label_set(Elm_Menu_Item *item, const char *label)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   eina_stringshare_replace(&item->label, label);
+
+   if (label)
+     edje_object_signal_emit(item->base.view, "elm,state,text,visible", "elm");
+   else
+     edje_object_signal_emit(item->base.view, "elm,state,text,hidden", "elm");
+
+   edje_object_message_signal_process(item->base.view);
+   edje_object_part_text_set(item->base.view, "elm.text", label);
+   _sizing_eval(item->base.widget);
+}
+
+/**
+ * Get the label of a menu item
+ *
+ * @param item The menu item object.
+ * @return The label of @p item
+ *
+ * @ingroup Menu
+ */
+EAPI const char *
+elm_menu_item_label_get(const Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->label;
+}
+
+/**
+ * Set the icon of a menu item
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ *
+ * @param item The menu item object.
+ * @param icon The icon object to set for @p item
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_item_icon_set(Elm_Menu_Item *item, const char *icon)
+{
+   char icon_tmp[512];
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   EINA_SAFETY_ON_NULL_RETURN(icon);
+   if (!*icon) return;
+   if ((item->icon_str) && (!strcmp(item->icon_str, icon))) return;
+   if ((snprintf(icon_tmp, sizeof(icon_tmp), "menu/%s", icon) > 0) &&
+       (elm_icon_standard_set(item->icon, icon_tmp)))
+     {
+        eina_stringshare_replace(&item->icon_str, icon);
+       edje_object_signal_emit(item->base.view, "elm,state,icon,visible", "elm");
+     }
+   else
+     edje_object_signal_emit(item->base.view, "elm,state,icon,hidden", "elm");
+   edje_object_message_signal_process(item->base.view);
+   _sizing_eval(item->base.widget);
+}
+
+/**
+ * Set the disabled state of @p item.
+ *
+ * @param item The menu item object.
+ * @param disabled The enabled/disabled state of the item
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_item_disabled_set(Elm_Menu_Item *item, Eina_Bool disabled)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (disabled == item->disabled) return;
+   item->disabled = disabled;
+   if (disabled)
+     {
+        edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
+        if (item->submenu.open) _submenu_hide(item);
+     }
+   else
+     edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm");
+   edje_object_message_signal_process(item->base.view);
+}
+
+/**
+ * Get the disabled state of @p item.
+ *
+ * @param item The menu item object.
+ * @return The enabled/disabled state of the item
+ *
+ * @ingroup Menu
+ */
+EAPI Eina_Bool
+elm_menu_item_disabled_get(const Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   if (!item) return EINA_FALSE;
+   return item->disabled;
+}
+
+/**
+ * Add a separator item to menu @p obj under @p parent.
+ *
+ * @param obj The menu object
+ * @param parent The item to add the separator under
+ *
+ * @return The created item or NULL on failure
+ *
+ * @ingroup Menu
+ */
+EAPI Elm_Menu_Item *
+elm_menu_item_separator_add(Evas_Object *obj, Elm_Menu_Item *parent)
+{
+   Elm_Menu_Item *subitem;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   /* don't add a separator as the first item */
+   if (!wd->items) return NULL;
+   /* don't allow adding more than one separator in a row */
+   if (parent) subitem = eina_list_last(parent->submenu.items)->data;
+   else subitem = eina_list_last(wd->items)->data;
+   if (subitem->separator) return NULL;
+
+   subitem = elm_widget_item_new(obj, Elm_Menu_Item);
+   if (!subitem) return NULL;
+   subitem->base.widget = obj;
+   subitem->separator = 1;
+   _item_separator_obj_create(subitem);
+   if (!parent)
+     {
+       elm_box_pack_end(wd->bx, subitem->base.view);
+       wd->items = eina_list_append(wd->items, subitem);
+     }
+   else
+     {
+       if (!parent->submenu.bx) _item_submenu_obj_create(parent);
+       elm_box_pack_end(parent->submenu.bx, subitem->base.view);
+       parent->submenu.items = eina_list_append(parent->submenu.items, subitem);
+     }
+   _sizing_eval(obj);
+   return subitem;
+}
+
+/**
+ * Get the icon object from a menu item
+ *
+ * @param item The menu item object
+ * @return The icon object or NULL if there's no icon
+ *
+ * @ingroup Menu
+ */
+EAPI const Evas_Object *
+elm_menu_item_object_icon_get(const Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return (const Evas_Object *)item->icon;
+}
+
+/**
+ * Get the string representation from the icon of a menu item
+ *
+ * @param item The menu item object.
+ * @return The string representation of @p item's icon or NULL
+ *
+ * @ingroup Menu
+ */
+EAPI const char *
+elm_menu_item_icon_get(const Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->icon_str;
+}
+
+/**
+ * Returns whether @p item is a separator.
+ *
+ * @param item The item to check
+ * @return If true, @p item is a separator
+ *
+ * @ingroup Menu
+ */
+EAPI Eina_Bool
+elm_menu_item_is_separator(Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return item->separator;
+}
+
+/**
+ * Deletes an item from the menu.
+ *
+ * @param item The item to delete.
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_item_del(Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   Elm_Menu_Item *_item;
+
+   elm_widget_item_pre_notify_del(item);
+
+   EINA_LIST_FREE(item->submenu.items, _item) elm_menu_item_del(_item);
+   if (item->label) eina_stringshare_del(item->label);
+   if (item->icon) evas_object_del(item->icon);
+   if (item->submenu.hv) evas_object_del(item->submenu.hv);
+   if (item->submenu.location) evas_object_del(item->submenu.location);
+
+   if (item->parent)
+     item->parent->submenu.items = eina_list_remove(item->parent->submenu.items, item);
+   else
+     {
+       Widget_Data *wd = elm_widget_data_get(item->base.widget);
+       wd->items = eina_list_remove(wd->items, item);
+     }
+
+   elm_widget_item_del(item);
+}
+
+/**
+ * Set the function called when a menu item is freed.
+ *
+ * @param item The item to set the callback on
+ * @param func The function called
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_item_del_cb_set(Elm_Menu_Item *item, Evas_Smart_Cb func)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_del_cb_set(item, func);
+}
+
+/**
+ * Returns the data associated with menu item @p item.
+ *
+ * @param item The item
+ * @return The data associated with @p item
+ *
+ * @ingroup Menu
+ */
+EAPI void *
+elm_menu_item_data_get(const Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_data_get(item);
+}
+
+/**
+ * Sets the data to be associated with menu item @p item.
+ *
+ * @param item The item
+ * @param data The data to be associated with @p item
+ *
+ * @ingroup Menu
+ */
+EAPI void
+elm_menu_item_data_set(Elm_Menu_Item *item, const void *data)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_data_set(item, data);
+}
+
+/**
+ * Returns a list of @p item's subitems.
+ *
+ * @param item The item
+ * @return An Eina_List* of @p item's subitems
+ *
+ * @ingroup Menu
+ */
+EAPI const Eina_List *
+elm_menu_item_subitems_get(const Elm_Menu_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->submenu.items;
+}
diff --git a/src/lib/elm_module.c b/src/lib/elm_module.c
new file mode 100644 (file)
index 0000000..ad78943
--- /dev/null
@@ -0,0 +1,216 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/* what are moodules in elementary for? for modularising behavior and features
+ * so they can be plugged in and out where you dont want the core source to
+ * always behave like that or do it that way. plug it at runtime!
+ * 
+ * they have module names (in config) and "slots" to plug that module into
+ * to server a purpose. eg you plug plugin "xx" into the "entry-copy-paste"
+ * slot so it would provide replacement copy & paste ui functionality and
+ * specific symbols
+ * 
+ * config is something like:
+ * 
+ * export ELM_MODULES="xx>slot1:yy>slot2"
+ * 
+ * where a module named xx is plugged into slot1 & yy is plugged into slot2
+ * 
+ * real examples:
+ * 
+ * export ELM_MODULES="my_module>entry/api"
+ * 
+ * this loads the module called "my_module" into the slot "entry/api" which
+ * is an api slot for entry modules to modify behavior and hook to
+ * creation/deletion of the entry as well as replace the longpress behavior.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <dlfcn.h>      /* dlopen,dlclose,etc */
+
+static Eina_Hash *modules = NULL;
+static Eina_Hash *modules_as = NULL;
+
+void
+_elm_module_init(void)
+{
+   modules = eina_hash_string_small_new(NULL);
+   modules_as = eina_hash_string_small_new(NULL);
+}
+
+void
+_elm_module_shutdown(void)
+{
+   // FIXME: unload all modules
+   if (modules) eina_hash_free(modules);
+   modules = NULL;
+   if (modules_as) eina_hash_free(modules_as);
+   modules_as = NULL;
+}
+
+void
+_elm_module_parse(const char *s)
+{
+   const char *p, *pe;
+   
+   p = s;
+   pe = p;
+   for (;;)
+     {
+        if ((*pe == ':') || (!*pe))
+          { // p -> pe == 'name:'
+             if (pe > p)
+               {
+                  char *n = malloc(pe - p + 1);
+                  if (n)
+                    {
+                       char *nn;
+                       
+                       strncpy(n, p, pe - p);
+                       n[pe - p] = 0;
+                       nn = strchr(n, '>');
+                       if (nn)
+                         {
+                            *nn = 0;
+                            nn++;
+                            _elm_module_add(n, nn);
+                         }
+                       free(n);
+                    }
+               }
+             if (!*pe) break;
+             p = pe + 1;
+             pe = p;
+          }
+        else
+          pe++;
+     }
+}
+
+Elm_Module *
+_elm_module_find_as(const char *as)
+{
+   Elm_Module *m;
+   
+   m = eina_hash_find(modules_as, as);
+   return m;
+}
+
+Elm_Module *
+_elm_module_add(const char *name, const char *as)
+{
+   Elm_Module *m;
+   char buf[PATH_MAX];
+
+   m = eina_hash_find(modules, name);
+   if (m)
+     {
+        m->references++;
+        return m;
+     }
+   m = calloc(1, sizeof(Elm_Module));
+   if (!m) return NULL;
+   m->version = 1;
+   if (name[0] != '/')
+     {
+        const char *home = getenv("HOME");
+        
+        if (home)
+          {
+             snprintf(buf, sizeof(buf), "%s/.elementary/modules/%s/%s/module" EFL_SHARED_EXTENSION, home, name, MODULE_ARCH);
+             m->handle = dlopen(buf, RTLD_NOW | RTLD_GLOBAL);
+             if (m->handle)
+               {
+                  m->init_func = dlsym(m->handle, "elm_modapi_init");
+                  if (m->init_func)
+                    {
+                       m->shutdown_func = dlsym(m->handle, "elm_modapi_shutdown");
+                       m->so_path = eina_stringshare_add(buf);
+                       m->name = eina_stringshare_add(name);
+                       snprintf(buf, sizeof(buf), "%s/.elementary/modules/%s/%s", home, name, MODULE_ARCH);
+                       m->bin_dir = eina_stringshare_add(buf);
+                       snprintf(buf, sizeof(buf), "%s/.elementary/modules/%s", home, name);
+                       m->data_dir = eina_stringshare_add(buf);
+                    }
+                  else
+                    {
+                       dlclose(m->handle);
+                       free(m);
+                       return NULL;
+                    }
+               }
+          }
+        if (!m->handle)
+          {
+             snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s/module" EFL_SHARED_EXTENSION, _elm_lib_dir, name, MODULE_ARCH);
+             m->handle = dlopen(buf, RTLD_NOW | RTLD_GLOBAL);
+             if (m->handle)
+               {
+                  m->init_func = dlsym(m->handle, "elm_modapi_init");
+                  if (m->init_func)
+                    {
+                       m->shutdown_func = dlsym(m->handle, "elm_modapi_shutdown");
+                       m->so_path = eina_stringshare_add(buf);
+                       m->name = eina_stringshare_add(name);
+                       snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s", _elm_lib_dir, name, MODULE_ARCH);
+                       m->bin_dir = eina_stringshare_add(buf);
+                       snprintf(buf, sizeof(buf), "%s/elementary/modules/%s", _elm_lib_dir, name);
+                       m->data_dir = eina_stringshare_add(buf);
+                    }
+                  else
+                    {
+                       dlclose(m->handle);
+                       free(m);
+                       return NULL;
+                    }
+               }
+          }
+     }
+   if (!m->handle)
+     {
+        free(m);
+        return NULL;
+     }
+   if (!m->init_func(m))
+     {
+        dlclose(m->handle);
+        eina_stringshare_del(m->name);
+        eina_stringshare_del(m->so_path);
+        eina_stringshare_del(m->data_dir);
+        eina_stringshare_del(m->bin_dir);
+        free(m);
+        return NULL;
+     }
+   m->references = 1;
+   eina_hash_direct_add(modules, m->name, m);
+   m->as = eina_stringshare_add(as);
+   eina_hash_direct_add(modules_as, m->as, m);
+   return m;
+}
+
+void
+_elm_module_del(Elm_Module *m)
+{
+   m->references--;
+   if (m->references > 0) return;
+   if (m->shutdown_func) m->shutdown_func(m);
+   eina_hash_del(modules, m->name, m);
+   eina_hash_del(modules_as, m->as, m);
+   if (m->api) free(m->api);
+   eina_stringshare_del(m->name);
+   eina_stringshare_del(m->as);
+   eina_stringshare_del(m->so_path);
+   eina_stringshare_del(m->data_dir);
+   eina_stringshare_del(m->bin_dir);
+   dlclose(m->handle);
+   free(m);
+}
+
+const void *
+_elm_module_symbol_get(Elm_Module *m, const char *name)
+{
+   return dlsym(m->handle, name);
+}
diff --git a/src/lib/elm_notify.c b/src/lib/elm_notify.c
new file mode 100644 (file)
index 0000000..18c407d
--- /dev/null
@@ -0,0 +1,625 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+
+/**
+ * @defgroup Notify notify
+ *
+ * Display a window in a particular region of the application (top,
+ * bottom, etc.  A timeout can be set to automatically close the
+ * window. This is so that, after an evas_object_show() on a notify
+ * object, if a timeout was set on it, it will <b>automatically</b>
+ * get hidden after that time.
+ *
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *notify, *content, *parent;
+
+   Elm_Notify_Orient orient;
+   Eina_Bool repeat_events;
+   Evas_Object *block_events;
+
+   double timeout;
+   Ecore_Timer *timer;
+};
+
+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 _signal_block_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _calc(Evas_Object *obj);
+static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _show(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static const char SIG_BLOCK_CLICKED[] = "block,clicked";
+static const char SIG_TIMEOUT[] = "timeout";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_BLOCK_CLICKED, ""},
+  {SIG_TIMEOUT, ""},
+  {NULL, NULL}
+};
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE, _resize, obj);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_SHOW, _show, obj);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _hide, obj);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_notify_parent_set(obj, NULL);
+   elm_notify_repeat_events_set(obj, EINA_TRUE);
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+   free(wd);
+}
+
+static void
+_notify_theme_apply(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *style = elm_widget_style_get(obj);
+
+   switch (wd->orient)
+     {
+      case ELM_NOTIFY_ORIENT_TOP:
+        _elm_theme_object_set(obj, wd->notify, "notify", "top", style);
+        break;
+      case ELM_NOTIFY_ORIENT_CENTER:
+        _elm_theme_object_set(obj, wd->notify, "notify", "center", style);
+        break;
+      case ELM_NOTIFY_ORIENT_BOTTOM:
+        _elm_theme_object_set(obj, wd->notify, "notify", "bottom", style);
+        break;
+      case ELM_NOTIFY_ORIENT_LEFT:
+        _elm_theme_object_set(obj, wd->notify, "notify", "left", style);
+        break;
+      case ELM_NOTIFY_ORIENT_RIGHT:
+        _elm_theme_object_set(obj, wd->notify, "notify", "right", style);
+        break;
+      case ELM_NOTIFY_ORIENT_TOP_LEFT:
+        _elm_theme_object_set(obj, wd->notify, "notify", "top_left", style);
+        break;
+      case ELM_NOTIFY_ORIENT_TOP_RIGHT:
+        _elm_theme_object_set(obj, wd->notify, "notify", "top_right", style);
+        break;
+      case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
+        _elm_theme_object_set(obj, wd->notify, "notify", "bottom_left", style);
+        break;
+      case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
+        _elm_theme_object_set(obj, wd->notify, "notify", "bottom_right", style);
+        break;
+      case ELM_NOTIFY_ORIENT_LAST:
+        break;
+     }
+}
+
+static void
+_block_events_theme_apply(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *style = elm_widget_style_get(obj);
+   _elm_theme_object_set(obj, wd->block_events, "notify", "block_events", style);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _notify_theme_apply(obj);
+   if (wd->block_events) _block_events_theme_apply(obj);
+   edje_object_scale_set(wd->notify, 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 x,y,w,h;
+   if (!wd) return;
+   if (!wd->parent) return;
+   evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
+   evas_object_move(obj, x, y);
+   evas_object_resize(obj, w, h);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _calc(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;
+
+   if (sub == wd->content)
+     {
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_RESIZE,
+                                            _content_resize, obj);
+       wd->content = NULL;
+     }
+}
+
+static void
+_signal_block_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
+}
+
+static void
+_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   _calc(obj);
+}
+
+static void
+_content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _calc(data);
+}
+
+static void
+_calc(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   Evas_Coord x, y, w, h;
+
+   if (!wd) return;
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   edje_object_size_min_get(wd->notify, &minw, &minh);
+   edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
+
+   if (wd->content)
+     {
+       int offx = (w - minw) / 2;
+       int offy = (h - minh) / 2;
+
+       switch (wd->orient)
+         {
+          case ELM_NOTIFY_ORIENT_TOP:
+             evas_object_move(wd->notify, x + offx, y);
+             break;
+          case ELM_NOTIFY_ORIENT_CENTER:
+             evas_object_move(wd->notify, x + offx, y + offy);
+             break;
+          case ELM_NOTIFY_ORIENT_BOTTOM:
+             evas_object_move(wd->notify, x + offx, y + h - minh);
+             break;
+          case ELM_NOTIFY_ORIENT_LEFT:
+             evas_object_move(wd->notify, x, y + offy);
+             break;
+          case ELM_NOTIFY_ORIENT_RIGHT:
+             evas_object_move(wd->notify, x + w - minw, y + offy);
+             break;
+          case ELM_NOTIFY_ORIENT_TOP_LEFT:
+             evas_object_move(wd->notify, x, y);
+             break;
+          case ELM_NOTIFY_ORIENT_TOP_RIGHT:
+             evas_object_move(wd->notify, x + w - minw, y);
+             break;
+          case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
+             evas_object_move(wd->notify, x, y + h - minh);
+             break;
+          case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
+             evas_object_move(wd->notify, x + w - minw, y + h - minh);
+             break;
+           case ELM_NOTIFY_ORIENT_LAST:
+             break;
+         }
+        evas_object_resize(wd->notify, minw, minh);
+     }
+    _sizing_eval(obj);
+}
+
+static Eina_Bool
+_timer_cb(void *data)
+{
+   Evas_Object *obj = data;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->timer = NULL;
+   evas_object_hide(obj);
+   evas_object_smart_callback_call(obj, SIG_TIMEOUT, NULL);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_timer_init(Evas_Object *obj, Widget_Data *wd)
+{
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+   if ((evas_object_visible_get(obj)) && (wd->timeout > 0.0))
+     wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
+}
+
+static void
+_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_show(wd->notify);
+   if (!wd->repeat_events)
+     evas_object_show(wd->block_events);
+   _timer_init(obj, wd);
+}
+
+static void
+_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_hide(wd->notify);
+   if (!wd->repeat_events)
+     evas_object_hide(wd->block_events);
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+}
+
+static void
+_parent_del(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->parent = NULL;
+   evas_object_hide(obj);
+}
+
+static void
+_parent_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->parent = NULL;
+   evas_object_hide(obj);
+}
+
+/**
+ * Add a new notify to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Notify
+ */
+EAPI Evas_Object *
+elm_notify_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "notify");
+   elm_widget_type_set(obj, "notify");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   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);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->repeat_events = EINA_TRUE;
+
+   wd->notify = edje_object_add(e);
+   wd->orient = -1;
+   elm_notify_orient_set(obj, ELM_NOTIFY_ORIENT_TOP);
+
+   elm_notify_parent_set(obj, parent);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _resize, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
+
+   _sizing_eval(obj);
+
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the content of the notify widget
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_notify_content_unset() function.
+ *
+ * @param obj The notify object
+ * @param content The content will be filled in this notify object
+ *
+ * @ingroup Notify
+ */
+EAPI void
+elm_notify_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content) evas_object_del(wd->content);
+   wd->content = content;
+
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+       evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE,
+                                      _content_resize, obj);
+       edje_object_part_swallow(wd->notify, "elm.swallow.content", content);
+     }
+   _sizing_eval(obj);
+   _calc(obj);
+}
+
+/**
+ * Unset the content of the notify widget
+ *
+ * Unparent and return the content object which was set for this widget
+ *
+ * @param obj The notify object
+ * @return The content that was being used
+ *
+ * @ingroup Notify
+ */
+EAPI Evas_Object *
+elm_notify_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *content;
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   content = wd->content;
+   elm_widget_sub_object_del(obj, wd->content);
+   edje_object_part_unswallow(wd->notify, wd->content);
+   wd->content = NULL;
+   return content;
+}
+
+/**
+ * Return the content of the notify widget
+ *
+ * @param obj The notify object
+ * @return The content that is being used
+ *
+ * @ingroup Notify
+ */
+EAPI Evas_Object *
+elm_notify_content_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->content;
+}
+
+/**
+ * Set the notify parent
+ *
+ * Once the parent object is set, a previously set one will be desconected
+ * and replaced.
+ *
+ * @param obj The notify object
+ * @param content The new parent
+ *
+ * @ingroup Notify
+ */
+EAPI void
+elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->parent)
+     {
+       evas_object_event_callback_del_full(wd->parent,
+                                            EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
+                                            _changed_size_hints, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
+                                            _changed_size_hints, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
+                                            _parent_del, obj);
+       evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
+                                            _parent_hide, obj);
+       wd->parent = NULL;
+     }
+   
+   if (parent)
+     {
+       wd->parent = parent;
+       evas_object_event_callback_add(parent,
+                                       EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _changed_size_hints, obj);
+       evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE,
+                                       _changed_size_hints, obj);
+       evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE,
+                                       _changed_size_hints, obj);
+       evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
+                                      _parent_del, obj);
+       evas_object_event_callback_add(parent, EVAS_CALLBACK_HIDE,
+                                       _parent_hide, obj);
+       edje_object_part_swallow(wd->notify, "elm.swallow.parent", parent);
+       _sizing_eval(obj);
+     }
+   _calc(obj);
+}
+
+/**
+ * Get the notify parent
+ *
+ * @param obj The notify object
+ * @return The parent
+ *
+ * @ingroup Notify
+ */
+EAPI Evas_Object *
+elm_notify_parent_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->parent;
+}
+
+/**
+ * Set the orientation
+ *
+ * @param obj The notify object
+ * @param orient The new orientation
+ */
+EAPI void
+elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->orient == orient) return;
+   wd->orient = orient;
+   _notify_theme_apply(obj);
+   _resize(obj, NULL, obj, NULL);
+}
+
+/**
+ * Return the orientation
+ * @param obj the notify objects
+ */
+EAPI Elm_Notify_Orient
+elm_notify_orient_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) -1;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return -1;
+   return wd->orient;
+}
+
+/**
+ * Set the time interval after which the notify window is going to be
+ * hidden.
+ *
+ * @param obj The notify object
+ * @param time The new timeout
+ *
+ * As said previously, an evas_object_show() on a notify object which
+ * had a timeout set by this function will trigger a timer to
+ * automatically hide it again. So, any order one calls
+ * elm_notify_timeout_set() and evas_object_show() on the same object
+ * (at hidden state) will behave the same.
+ *
+ * @note Set a value <= 0.0 to disable a running timer.
+ *
+ * @note If the value > 0.0 and the notify is previously visible, the
+ * timer will be started with this value, canceling any running timer.
+ *
+ */
+EAPI void
+elm_notify_timeout_set(Evas_Object *obj, double timeout)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->timeout = timeout;
+   _timer_init(obj, wd);
+}
+
+/**
+ * Return the timeout value (in seconds)
+ * @param obj the notify object
+ */
+EAPI double
+elm_notify_timeout_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->timeout;
+}
+
+/**
+ * When true if the user clicks outside the window the events will be
+ * catch by the others widgets, else the events are block and the signal
+ * dismiss will be sent when the user click outside the window.
+ *
+ * @note The default value is EINA_TRUE.
+ *
+ * @param obj The notify object
+ * @param repeats EINA_TRUE Events are repeats, else no
+ */
+EAPI void
+elm_notify_repeat_events_set(Evas_Object *obj, Eina_Bool repeat)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (repeat == wd->repeat_events) return;
+   wd->repeat_events = repeat;
+   if (!repeat)
+     {
+       wd->block_events = edje_object_add(evas_object_evas_get(obj));
+       _block_events_theme_apply(obj);
+        elm_widget_resize_object_set(obj, wd->block_events);
+       edje_object_signal_callback_add(wd->block_events, "elm,action,clicked",
+                                        "elm", _signal_block_clicked, obj);
+     }
+   else
+     evas_object_del(wd->block_events);
+}
+
+/**
+ * Return true if events are repeat below the notify object
+ * @param obj the notify object
+ */
+EAPI Eina_Bool
+elm_notify_repeat_events_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->repeat_events;
+}
+
diff --git a/src/lib/elm_pager.c b/src/lib/elm_pager.c
new file mode 100644 (file)
index 0000000..0c6c67e
--- /dev/null
@@ -0,0 +1,442 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Pager Pager
+ *
+ * The pager is an object that allows flipping (with animation) between 1 or
+ * more “pages” of objects, much like a stack of windows within the window.
+ *
+ * Objects can be pushed or popped from the stack or deleted as normal.
+ * Pushes and pops will animate (and a pop will delete the object once the
+ * animation is finished). Any object in the pager can be promoted to the top
+ * (from its current stacking position) as well. Objects are pushed to the
+ * top with elm_pager_content_push() and when the top item is no longer
+ * wanted, simply pop it with elm_pager_content_pop() and it will also be
+ * deleted. Any object you wish to promote to the top that is already in the
+ * pager, simply use elm_pager_content_promote(). If an object is no longer
+ * needed and is not the top item, just delete it as normal. You can query
+ * which objects are the top and bottom with elm_pager_content_bottom_get()
+ * and elm_pager_content_top_get().
+ */
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Item Item;
+
+struct _Widget_Data
+{
+   Eina_List *stack;
+   Item *top, *oldtop;
+   Evas_Object *rect, *clip;
+};
+
+struct _Item
+{
+   Evas_Object *obj, *base, *content;
+   Evas_Coord minw, minh;
+   Eina_Bool popme : 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 _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;
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Item *it;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->stack, l, it)
+     {
+        _elm_theme_object_set(obj, it->base,  "pager", "base",
+                              elm_widget_style_get(obj));
+        edje_object_scale_set(it->base, elm_widget_scale_get(obj) *
+                              _elm_config->scale);
+     }
+   _sizing_eval(obj);
+}
+
+static Eina_Bool
+_elm_pager_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *cur;
+
+   if ((!wd) || (!wd->top))
+     return EINA_FALSE;
+
+   cur = wd->top->content;
+
+   /* Try Focus cycle in subitem */
+   return elm_widget_focus_next_get(cur, dir, next);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   Eina_List *l;
+   Item *it;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->stack, l, it)
+     {
+       if (it->minw > minw) minw = it->minw;
+       if (it->minh > minh) minh = it->minh;
+     }
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Item *it = data;
+   Evas_Coord minw = -1, minh = -1;
+   evas_object_size_hint_min_get(it->content, &minw, &minh);
+   // FIXME: why is this needed? how does edje get this unswallowed or
+   // lose its callbacks to edje
+   edje_object_part_swallow(it->base, "elm.swallow.content", it->content);
+   edje_object_size_min_calc(it->base, &it->minw, &it->minh);
+   _sizing_eval(it->obj);
+}
+
+static void
+_eval_top(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Item *ittop;
+   if (!wd) return;
+   if (!wd->stack) return;
+   ittop = eina_list_last(wd->stack)->data;
+   if (ittop != wd->top)
+     {
+       Evas_Object *o;
+       const char *onshow, *onhide;
+
+       if (wd->top)
+         {
+            o = wd->top->base;
+            if (wd->top->popme)
+               edje_object_signal_emit(o, "elm,action,pop", "elm");
+            else
+               edje_object_signal_emit(o, "elm,action,hide", "elm");
+            onhide = edje_object_data_get(o, "onhide");
+            if (onhide)
+              {
+                 if (!strcmp(onhide, "raise")) evas_object_raise(o);
+                 else if (!strcmp(onhide, "lower")) evas_object_lower(o);
+              }
+         }
+       wd->oldtop = wd->top;
+       wd->top = ittop;
+       o = wd->top->base;
+       evas_object_show(o);
+        if (wd->oldtop)
+          {
+             if (elm_object_focus_get(wd->oldtop->content))
+               elm_object_focus(wd->top->content);
+             if (wd->oldtop->popme)
+               edje_object_signal_emit(o, "elm,action,show", "elm");
+             else
+               edje_object_signal_emit(o, "elm,action,push", "elm");
+          }
+        else
+          edje_object_signal_emit(o, "elm,action,push", "elm");
+       onshow = edje_object_data_get(o, "onshow");
+       if (onshow)
+         {
+            if (!strcmp(onshow, "raise")) evas_object_raise(o);
+            else if (!strcmp(onshow, "lower")) evas_object_lower(o);
+         }
+     }
+}
+
+static void
+_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord x, y;
+   Eina_List *l;
+   Item *it;
+   if (!wd) return;
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   EINA_LIST_FOREACH(wd->stack, l, it)
+     evas_object_move(it->base, x, y);
+}
+
+static void
+_sub_del(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Object *sub = event_info;
+   Eina_List *l;
+   Item *it;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->stack, l, it)
+     {
+       if (it->content == sub)
+         {
+            wd->stack = eina_list_remove_list(wd->stack, l);
+            evas_object_event_callback_del_full
+               (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, it);
+            evas_object_del(it->base);
+            _eval_top(it->obj);
+            free(it);
+            return;
+         }
+     }
+}
+
+static void
+_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{   
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord w, h;
+   Eina_List *l;
+   Item *it;
+   if (!wd) return;
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   EINA_LIST_FOREACH(wd->stack, l, it) evas_object_resize(it->base, w, h);
+}
+
+static void
+_signal_hide_finished(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Item *it = data;
+   Evas_Object *obj2 = it->obj;
+   evas_object_hide(it->base);
+   edje_object_signal_emit(it->base, "elm,action,reset", "elm");
+   evas_object_smart_callback_call(obj2, "hide,finished", it->content);
+   edje_object_message_signal_process(it->base);
+   evas_object_hide(it->content);
+   if (it->popme) evas_object_del(it->content);
+   _sizing_eval(obj2);
+}
+
+/**
+ * Add a new pager to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Pager
+ */
+EAPI Evas_Object *
+elm_pager_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "pager");
+   elm_widget_type_set(obj, "pager");
+   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_focus_next_hook_set(obj, _elm_pager_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->clip = evas_object_rectangle_add(e);
+   elm_widget_resize_object_set(obj, wd->clip);
+   elm_widget_sub_object_add(obj, wd->clip);
+
+   wd->rect = evas_object_rectangle_add(e);
+   elm_widget_sub_object_add(obj, wd->rect);
+   evas_object_color_set(wd->rect, 255, 255, 255, 0); 
+   evas_object_clip_set(wd->rect, wd->clip);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Push an object to the top of the pager stack (and show it)
+ *
+ * The object pushed becomes a child of the pager and will be controlled
+ * it and deleted when the pager is deleted.
+ *
+ * @param obj The pager object
+ * @param content The object to push
+ *
+ * @ingroup Pager
+ */
+EAPI void
+elm_pager_content_push(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Item *it = ELM_NEW(Item);
+   Evas_Coord x, y, w, h;
+   if (!wd) return;
+   if (!it) return;
+   it->obj = obj;
+   it->content = content;
+   it->base = edje_object_add(evas_object_evas_get(obj));
+   evas_object_smart_member_add(it->base, obj);
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   evas_object_move(it->base, x, y);
+   evas_object_resize(it->base, w, h);
+   evas_object_clip_set(it->base, wd->clip);
+   elm_widget_sub_object_add(obj, it->base);
+   elm_widget_sub_object_add(obj, it->content);
+   _elm_theme_object_set(obj, it->base,  "pager", "base", elm_widget_style_get(obj));
+   edje_object_signal_callback_add(it->base, "elm,action,hide,finished", "", 
+                                   _signal_hide_finished, it);
+   evas_object_event_callback_add(it->content,
+                                  EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                  _changed_size_hints, it);
+   edje_object_part_swallow(it->base, "elm.swallow.content", it->content);
+   edje_object_size_min_calc(it->base, &it->minw, &it->minh);
+   evas_object_data_set(it->base, "_elm_leaveme", obj);
+   evas_object_show(it->content);
+   wd->stack = eina_list_append(wd->stack, it);
+   _eval_top(obj);
+   _sizing_eval(obj);
+}
+
+/**
+ * Pop the object that is on top of the stack
+ *
+ * This pops the object that is on top (visible) in the pager, makes it
+ * disappear, then deletes the object. The object that was underneath it
+ * on the stack will become visible.
+ *
+ * @param obj The pager object
+ *
+ * @ingroup Pager
+ */
+EAPI void
+elm_pager_content_pop(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *ll;
+   Item *it;
+   if (!wd) return;
+   if (!wd->stack) return;
+   it = eina_list_last(wd->stack)->data;
+   it->popme = EINA_TRUE;
+   ll = eina_list_last(wd->stack);
+   if (ll)
+     {
+       ll = ll->prev;
+       if (!ll)
+         {
+            Evas_Object *o;
+            const char *onhide;
+
+            wd->top = it;
+            o = wd->top->base;
+            edje_object_signal_emit(o, "elm,action,pop", "elm");
+            onhide = edje_object_data_get(o, "onhide");
+            if (onhide)
+              {
+                 if (!strcmp(onhide, "raise")) evas_object_raise(o);
+                 else if (!strcmp(onhide, "lower")) evas_object_lower(o);
+              }
+            wd->top = NULL;
+         }
+       else
+         {
+            it = ll->data;
+            elm_pager_content_promote(obj, it->content);
+         }
+     }
+}
+
+/**
+ * Promote an object already in the pager stack to the top of the stack
+ *
+ * This will take the indicated object and promote it to the top of the stack
+ * as if it had been pushed there. The object must already be inside the
+ * pager stack to work.
+ *
+ * @param obj The pager object
+ * @param content The object to promote
+ *
+ * @ingroup Pager
+ */
+EAPI void
+elm_pager_content_promote(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Item *it;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->stack, l, it)
+     {
+       if (it->content == content)
+         {
+            wd->stack = eina_list_remove_list(wd->stack, l);
+            wd->stack = eina_list_append(wd->stack, it);
+            _eval_top(obj);
+            return;
+         }
+     }
+}
+
+/**
+ * Return the object at the bottom of the pager stack
+ *
+ * @param obj The pager object
+ * @return The bottom object or NULL if none
+ *
+ * @ingroup Pager
+ */
+EAPI Evas_Object *
+elm_pager_content_bottom_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Item *it;
+   if (!wd) return NULL;
+   if (!wd->stack) return NULL;
+   it = wd->stack->data;
+   return it->content;
+}
+
+/**
+ * Return the object at the top of the pager stack
+ *
+ * @param obj The pager object
+ * @return The top object or NULL if none
+ *
+ * @ingroup Pager
+ */
+EAPI Evas_Object *
+elm_pager_content_top_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->top) return NULL;
+   return wd->top->content;
+}
+
diff --git a/src/lib/elm_panel.c b/src/lib/elm_panel.c
new file mode 100644 (file)
index 0000000..c6b7a9f
--- /dev/null
@@ -0,0 +1,469 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Panel Panel
+ *
+ * A panel is a type of animated container that contains subobjects.  It
+ * can be expanded or contracted.
+ *
+ * Orientations are as follows:
+ * ELM_PANEL_ORIENT_TOP
+ * ELM_PANEL_ORIENT_BOTTOM
+ * ELM_PANEL_ORIENT_LEFT
+ * ELM_PANEL_ORIENT_RIGHT
+ * NOTE: Only LEFT and RIGHT orientations are implemented.
+ *
+ * THIS WIDGET IS UNDER CONSTRUCTION!
+ */
+
+typedef struct _Widget_Data Widget_Data;
+struct _Widget_Data 
+{
+   Evas_Object *scr, *bx, *content;
+   Elm_Panel_Orient orient;
+   Eina_Bool hidden : 1;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _resize(void *data, Evas *evas, Evas_Object *obj, void *event);
+static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
+static void _toggle_panel(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;
+   if (wd->scr)
+     {
+        Evas_Object *edj;
+        const char *str;
+
+        elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base",
+                                            elm_widget_style_get(obj));
+        //   scale = (elm_widget_scale_get(obj) * _elm_config->scale);
+        //   edje_object_scale_set(wd->scr, scale);
+        edj = elm_smart_scroller_edje_object_get(wd->scr);
+        str = edje_object_data_get(edj, "focus_highlight");
+        if ((str) && (!strcmp(str, "on")))
+          elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
+        else
+          elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
+     }
+   _sizing_eval(obj);
+}
+
+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))
+     evas_object_focus_set(obj, EINA_TRUE);
+   else
+     evas_object_focus_set(obj, EINA_FALSE);
+}
+
+static Eina_Bool
+_elm_panel_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *cur;
+
+   if ((!wd) || (!wd->content))
+     return EINA_FALSE;
+
+   cur = wd->content;
+
+   /* Try Focus cycle in subitem */
+   if (!wd->hidden)
+      return elm_widget_focus_next_get(cur, dir, next);
+
+   /* Return */
+   *next = (Evas_Object *)obj;
+   return !elm_widget_focus_get(obj);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+        emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
+        emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(
+        elm_smart_scroller_edje_object_get(wd->scr), emission, source,
+        func_cb, data);
+}
+
+static void 
+_sizing_eval(Evas_Object *obj) 
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord mw = -1, mh = -1;
+   Evas_Coord vw = 0, vh = 0;
+   Evas_Coord w, h;
+   if (!wd) return;
+   evas_object_smart_calculate(wd->bx);
+   edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), 
+                             &mw, &mh);
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   if (w < mw) w = mw;
+   if (h < mh) h = mh;
+   evas_object_resize(wd->scr, w, h);
+
+   evas_object_size_hint_min_get(wd->bx, &mw, &mh);
+   if (w > mw) mw = w;
+   if (h > mh) mh = h;
+   evas_object_resize(wd->bx, mw, mh);
+
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
+   mw = mw + (w - vw);
+   mh = mh + (h - vh);
+   evas_object_size_hint_min_set(obj, mw, mh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void 
+_resize(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord mw, mh, vw, vh, w, h;
+   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) || (vh >= mh))
+     {
+        if ((w != vw) || (h != vh)) evas_object_resize(wd->bx, vw, vh);
+     }
+}
+
+static void 
+_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data) 
+{
+   Widget_Data *wd = data;
+   if (!wd) return;
+   _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE);
+}
+
+static void 
+_toggle_panel(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__) 
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->hidden) 
+     {
+        edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), 
+                                "elm,action,show", "elm");
+        wd->hidden = EINA_FALSE;
+        evas_object_repeat_events_set(obj, EINA_FALSE);
+     }
+   else
+     {
+        edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), 
+                                "elm,action,hide", "elm");
+        wd->hidden = EINA_TRUE;
+        evas_object_repeat_events_set(obj, EINA_TRUE);
+        if (elm_widget_focus_get(wd->content))
+          {
+             elm_widget_focused_object_clear(obj);
+             elm_widget_focus_steal(obj);
+          }
+     }
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if ((src != obj) || (type != EVAS_CALLBACK_KEY_DOWN)) return EINA_FALSE;
+
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+
+   if ((strcmp(ev->keyname, "Return")) &&
+       (strcmp(ev->keyname, "KP_Enter")) &&
+       (strcmp(ev->keyname, "space")))
+     return EINA_FALSE;
+
+   _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+}
+
+/**
+ * Adds a panel object
+ *
+ * @param parent The parent object
+ *
+ * @return The panel object, or NULL on failure
+ *
+ * @ingroup Panel
+ */
+EAPI Evas_Object *
+elm_panel_add(Evas_Object *parent) 
+{
+   Evas_Object *obj;
+   Evas *evas;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   evas = evas_object_evas_get(parent);
+   if (!evas) return NULL;
+   obj = elm_widget_add(evas);
+   ELM_SET_WIDTYPE(widtype, "panel");
+   elm_widget_type_set(obj, "panel");
+   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_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_widget_focus_next_hook_set(obj, _elm_panel_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->scr = elm_smart_scroller_add(evas);
+   elm_smart_scroller_widget_set(wd->scr, obj);
+   _theme_hook(obj);
+   elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE, EINA_FALSE);
+   elm_widget_resize_object_set(obj, wd->scr);
+   elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF, 
+                                 ELM_SMART_SCROLLER_POLICY_OFF);
+
+   wd->hidden = EINA_FALSE;
+   wd->orient = ELM_PANEL_ORIENT_LEFT;
+
+   wd->bx = evas_object_box_add(evas);
+   evas_object_size_hint_align_set(wd->bx, 0.5, 0.5);
+   evas_object_box_layout_set(wd->bx, _layout, wd, NULL);
+   elm_widget_sub_object_add(obj, wd->bx);
+   elm_smart_scroller_child_set(wd->scr, wd->bx);
+   evas_object_show(wd->bx);
+
+   edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr), 
+                                   "elm,action,panel,toggle", "*", 
+                                   _toggle_panel, obj);
+
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Sets the orientation of the panel
+ *
+ * @param parent The parent object
+ * @param orient The panel orientation.  Can be one of the following:
+ * ELM_PANEL_ORIENT_TOP
+ * ELM_PANEL_ORIENT_BOTTOM
+ * ELM_PANEL_ORIENT_LEFT
+ * ELM_PANEL_ORIENT_RIGHT
+ *
+ * NOTE: Only LEFT and RIGHT orientations are implemented.
+ *
+ * @ingroup Panel
+ */
+EAPI void 
+elm_panel_orient_set(Evas_Object *obj, Elm_Panel_Orient orient) 
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->orient = orient;
+   switch (orient) 
+     {
+     case ELM_PANEL_ORIENT_TOP:
+        elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "top");
+        break;
+     case ELM_PANEL_ORIENT_BOTTOM:
+        elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "bottom");
+        break;
+     case ELM_PANEL_ORIENT_LEFT:
+        elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "left");
+        break;
+     case ELM_PANEL_ORIENT_RIGHT:
+        elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "right");
+        break;
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the orientation of the panel.
+ *
+ * @param obj The panel object
+ * @return The Elm_Panel_Orient, or ELM_PANEL_ORIENT_LEFT on failure.
+ *
+ * @ingroup Panel
+ */
+EAPI Elm_Panel_Orient
+elm_panel_orient_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_PANEL_ORIENT_LEFT;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_PANEL_ORIENT_LEFT;
+   return wd->orient;   
+}
+
+/**
+ * Set the content of the panel.
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_panel_content_unset() function.
+ *
+ * @param obj The panel object
+ * @param content The panel content
+ *
+ * @ingroup Panel
+ */
+EAPI void
+elm_panel_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content)
+     evas_object_box_remove_all(wd->bx, EINA_TRUE);
+   wd->content = content;
+   if (content)
+     {
+       evas_object_box_append(wd->bx, wd->content);
+       evas_object_show(wd->content);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the content of the panel.
+ *
+ * Return the content object which is set for this widget.
+ *
+ * @param obj The panel object
+ * @return The content that is being used
+ *
+ * @ingroup Panel
+ */
+EAPI Evas_Object *
+elm_panel_content_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->content;
+}
+
+/**
+ * Unset the content of the panel.
+ *
+ * Unparent and return the content object which was set for this widget.
+ *
+ * @param obj The panel object
+ * @return The content that was being used
+ *
+ * @ingroup Panel
+ */
+EAPI Evas_Object *
+elm_panel_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *content;
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   content = wd->content;
+   evas_object_box_remove_all(wd->bx, EINA_FALSE);
+   wd->content = NULL;
+   return content;
+}
+
+/**
+ * Set the state of the panel.
+ *
+ * @param obj The panel object
+ * @param hidden If true, the panel will run the edje animation to contract
+ *
+ * @ingroup Panel
+ */
+EAPI void
+elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->hidden == hidden) return;
+   _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
+}
+
+/**
+ * Get the state of the panel.
+ *
+ * @param obj The panel object
+ * @param hidden If true, the panel is in the "hide" state
+ *
+ * @ingroup Panel
+ */
+EAPI Eina_Bool
+elm_panel_hidden_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->hidden;
+}
+
+/**
+ * Toggle the state of the panel from code
+ *
+ * @param obj The panel object
+ *
+ * @ingroup Panel
+ */
+EAPI void
+elm_panel_toggle(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->hidden = !(wd->hidden);
+   _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
+}
diff --git a/src/lib/elm_panes.c b/src/lib/elm_panes.c
new file mode 100644 (file)
index 0000000..be82d21
--- /dev/null
@@ -0,0 +1,429 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Panes panes
+ *
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *panes;
+
+   struct
+     {
+       Evas_Object *left;
+       Evas_Object *right;
+     } contents;
+
+   struct
+     {
+       int x_diff;
+       int y_diff;
+       Eina_Bool move;
+     } move;
+
+   Eina_Bool clicked_double;
+   Eina_Bool horizontal;
+};
+
+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
+_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 char *style = elm_widget_style_get(obj);
+   double size;
+
+   if (!wd) return;
+   size = elm_panes_content_left_size_get(obj);
+   
+   if (wd->horizontal)
+     _elm_theme_object_set(obj, wd->panes, "panes", "horizontal", style);
+   else
+     _elm_theme_object_set(obj, wd->panes, "panes", "vertical", style);
+
+   if (wd->contents.left)
+     edje_object_part_swallow(wd->panes, "elm.swallow.left", wd->contents.left);
+   if (wd->contents.right)
+     edje_object_part_swallow(wd->panes, "elm.swallow.right", wd->contents.right);
+
+   edje_object_scale_set(wd->panes, elm_widget_scale_get(obj) *
+                         _elm_config->scale);
+   _sizing_eval(obj);
+   elm_panes_content_left_size_set(obj, size);
+}
+
+static Eina_Bool
+_elm_panes_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd)
+     return EINA_FALSE;
+
+   double w, h;
+   edje_object_part_drag_value_get(wd->panes, "elm.bar", &w, &h);
+   if (((wd->horizontal) && ( h == 0.0 )) || ((!wd->horizontal) && ( w == 0.0 )))
+     return elm_widget_focus_next_get(wd->contents.right, dir, next);
+
+   Evas_Object *chain[2];
+
+   /* Direction */
+   if (dir == ELM_FOCUS_PREVIOUS)
+     {
+        chain[0] = wd->contents.right;
+        chain[1] = wd->contents.left;
+     }
+   else if (dir == ELM_FOCUS_NEXT)
+     {
+        chain[0] = wd->contents.left;
+        chain[1] = wd->contents.right;
+     }
+   else
+     return EINA_FALSE;
+
+   unsigned char i = elm_widget_focus_get(chain[1]);
+
+   if (elm_widget_focus_next_get(chain[i], dir, next))
+     return EINA_TRUE;
+
+   i = !i;
+
+   Evas_Object *to_focus;
+   if (elm_widget_focus_next_get(chain[i], dir, &to_focus))
+     {
+        *next = to_focus;
+        return !!i;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_sub_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *sub = event_info;
+
+   if (!wd) return;
+   if (sub == wd->contents.left)
+     {
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       wd->contents.left = NULL;
+       _sizing_eval(obj);
+     }
+   else if (sub == wd->contents.right)
+     {
+       evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+       wd->contents.right= NULL;
+       _sizing_eval(obj);
+     }
+}
+
+static void
+_clicked(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "clicked", NULL);
+}
+
+static void
+_clicked_double(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   wd->clicked_double = EINA_TRUE;
+}
+
+static void
+_press(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "press", NULL);
+}
+
+static void
+_unpress(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   evas_object_smart_callback_call(data, "unpress", NULL);
+
+   if (wd->clicked_double)
+     {
+       evas_object_smart_callback_call(data, "clicked,double", NULL);
+       wd->clicked_double = EINA_FALSE;
+     }
+}
+
+/**
+ * Add a new panes to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Panel
+ */
+EAPI Evas_Object *
+elm_panes_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "panes");
+   elm_widget_type_set(obj, "panes");
+   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_focus_next_hook_set(obj, _elm_panes_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->panes = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->panes, "panes", "vertical", "default");
+   elm_widget_resize_object_set(obj, wd->panes);
+   evas_object_show(wd->panes);
+
+   elm_panes_content_left_size_set(obj, 0.5);
+
+   edje_object_signal_callback_add(wd->panes, "elm,action,click", "", 
+                                   _clicked, obj);
+   edje_object_signal_callback_add(wd->panes, "elm,action,click,double", "", 
+                                   _clicked_double, obj);
+   edje_object_signal_callback_add(wd->panes, "elm,action,press", "", 
+                                   _press, obj);
+   edje_object_signal_callback_add(wd->panes, "elm,action,unpress", "", 
+                                   _unpress, obj);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, 
+                                  _changed_size_hints, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+
+/**
+ * Set the left content of the panes widget.
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_panes_content_left_unset() function.
+ *
+ * @param obj The panes object
+ * @param content The new left content object
+ *
+ * @ingroup Panes
+ */
+EAPI void
+elm_panes_content_left_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (wd->contents.left)
+     {
+       evas_object_del(wd->contents.left);
+       wd->contents.left = NULL;
+     }
+   if (content)
+     {
+       wd->contents.left = content;
+       elm_widget_sub_object_add(obj, content);
+       edje_object_part_swallow(wd->panes, "elm.swallow.left", content);
+     }
+}
+
+/**
+ * Set the right content of the panes widget.
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_panes_content_right_unset() function.
+ *
+ * @param obj The panes object
+ * @param content The new right content object
+ *
+ * @ingroup Panes
+ */
+EAPI void
+elm_panes_content_right_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (wd->contents.right)
+     {
+       evas_object_del(wd->contents.right);
+       wd->contents.right = NULL;
+     }
+   if (content)
+     {
+       wd->contents.right = content;
+       elm_widget_sub_object_add(obj, content);
+       edje_object_part_swallow(wd->panes, "elm.swallow.right", content);
+     }
+}
+
+/**
+ * Get the left content used for the panes
+ *
+ * Return the left content object which is set for this widget.
+ *
+ * @param obj The panes object
+ * @return The left content object that is being used
+ *
+ * @ingroup Panes
+ */
+EAPI Evas_Object *
+elm_panes_content_left_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return wd->contents.left;
+}
+
+/**
+ * Get the right content used for the panes
+ *
+ * Return the right content object which is set for this widget.
+ *
+ * @param obj The panes object
+ * @return The right content object that is being used
+ *
+ * @ingroup Panes
+ */
+EAPI Evas_Object *
+elm_panes_content_right_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return wd->contents.right;
+}
+
+/**
+ * Unset the left content used for the panes
+ *
+ * Unparent and return the left content object which was set for this widget.
+ *
+ * @param obj The panes object
+ * @return The left content object that was being used
+ *
+ * @ingroup Panes
+ */
+EAPI Evas_Object *
+elm_panes_content_left_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->contents.left) return NULL;
+   Evas_Object *content = wd->contents.left;
+   elm_widget_sub_object_del(obj, content);
+   edje_object_part_unswallow(wd->panes, content);
+   wd->contents.left = NULL;
+   return content;
+}
+
+/**
+ * Unset the right content used for the panes
+ *
+ * Unparent and return the right content object which was set for this widget.
+ *
+ * @param obj The panes object
+ * @return The right content object that was being used
+ *
+ * @ingroup Panes
+ */
+EAPI Evas_Object *
+elm_panes_content_right_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->contents.right) return NULL;
+   Evas_Object *content = wd->contents.right;
+   elm_widget_sub_object_del(obj, content);
+   edje_object_part_unswallow(wd->panes, content);
+   wd->contents.right = NULL;
+   return content;
+}
+
+EAPI double 
+elm_panes_content_left_size_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double w, h;
+
+   edje_object_part_drag_value_get(wd->panes, "elm.bar", &w, &h);
+   if (wd->horizontal) return h;
+   else return w;
+}
+
+EAPI void 
+elm_panes_content_left_size_set(Evas_Object *obj, double size)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (size < 0.0) size = 0.0;
+   else if (size > 1.0) size = 1.0;
+   if (wd->horizontal)
+     edje_object_part_drag_value_set(wd->panes, "elm.bar", 0.0, size);
+   else
+     edje_object_part_drag_value_set(wd->panes, "elm.bar", size, 0.0);
+}
+
+EAPI void 
+elm_panes_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   wd->horizontal = horizontal;
+   _theme_hook(obj);
+   elm_panes_content_left_size_set(obj, 0.5);
+}
+
+EAPI Eina_Bool 
+elm_panes_horizontal_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   return wd->horizontal;
+}
diff --git a/src/lib/elm_photo.c b/src/lib/elm_photo.c
new file mode 100644 (file)
index 0000000..c69ed79
--- /dev/null
@@ -0,0 +1,342 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Photo Photo
+ *
+ * For displaying the photo of a person (contact). Simple yet
+ * with a very specific purpose. 
+ * 
+ * Signals that you can add callbacks for are:
+ *
+ *  - clicked: This is called when a user has clicked the photo
+ *  - drop: Something was dropped on the widget
+ *  - drag,start: Someone started dragging the image out of the object
+ *  - drag,end: Dragged item was dropped (somewhere)
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *frm;
+   Evas_Object *img;
+   int size;
+   Eina_Bool fill;
+   Ecore_Timer *longtimer;
+};
+
+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 _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _mouse_move(void *data, Evas *e, 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;
+   _elm_theme_object_set(obj, wd->frm, "photo", "base", 
+                         elm_widget_style_get(obj));
+   edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
+   edje_object_scale_set(wd->frm, 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;
+   if (wd->size > 0) 
+     {
+        double scale = 0.0;
+
+        scale = (wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
+        evas_object_size_hint_min_set(wd->img, scale, scale);
+        edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
+        elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+        edje_object_size_min_restricted_calc(wd->frm, &minw, &minh, minw, minh);
+        elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+        maxw = minw;
+        maxh = minh;
+        evas_object_size_hint_min_set(obj, minw, minh);
+        evas_object_size_hint_max_set(obj, maxw, maxh);
+     }
+}
+
+static void
+_icon_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Coord w, h;
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd) return;
+   if (wd->fill) 
+     {
+        Edje_Message_Int_Set *msg;
+        Evas_Object *icon = _els_smart_icon_object_get(wd->img);
+
+        evas_object_geometry_get(icon, NULL, NULL, &w, &h);
+        msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
+        msg->count=2;
+        msg->val[0] = (int)w;
+        msg->val[1] = (int)h;
+
+        edje_object_message_send(wd->frm, EDJE_MESSAGE_INT_SET, 0, msg);
+     }
+}
+
+
+static void
+_drag_done_cb(void *unused __UNUSED__, Evas_Object *obj)
+{
+   elm_object_scroll_freeze_pop(obj);
+   evas_object_smart_callback_call(obj, "drag,end", NULL);
+}
+
+static Eina_Bool
+_longpress(void *objv)
+{
+   Widget_Data *wd = elm_widget_data_get(objv);
+   Evas_Object *tmp;
+   const char *file;
+   char *buf;
+
+   DBG("Long press: start drag!");
+   wd->longtimer = NULL; /* clear: must return NULL now */
+   evas_object_event_callback_del(objv, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move);
+
+   tmp = _els_smart_icon_object_get(wd->img);
+   file = NULL;
+   evas_object_image_file_get(tmp,&file,NULL);
+   if (file)
+     {
+        /* FIXME: Deal with relative paths */
+        buf = malloc(strlen(file) + strlen("file://") + 1);
+        sprintf(buf, "%s%s","file://",file);
+        elm_drag_start(objv, ELM_SEL_FORMAT_IMAGE, buf, _drag_done_cb, NULL);
+        free(buf);
+     }
+   elm_object_scroll_freeze_push(objv);
+
+   evas_object_smart_callback_call(objv, "drag,start", NULL);
+
+   return 0; /* Don't call again */
+}
+
+static void
+_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Move *move = event;
+
+   /* Sanity */
+   if (!wd->longtimer)
+     {
+        evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move);
+        return;
+     }
+
+   /* if the event is held, stop waiting */
+   if (move->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     {
+        /* Moved too far: No longpress for you! */
+        ecore_timer_del(wd->longtimer);
+        wd->longtimer = NULL;
+        evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                       _mouse_move);
+     }
+}
+
+static void
+_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (wd->longtimer) ecore_timer_del(wd->longtimer);
+
+   /* FIXME: Hard coded timeout */
+   wd->longtimer = ecore_timer_add(0.7, _longpress, data);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _mouse_move, data);
+}
+
+static void
+_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if ((wd) && (wd->longtimer))
+     {
+        ecore_timer_del(wd->longtimer);
+        wd->longtimer = NULL;
+     }
+
+   evas_object_smart_callback_call(data, "clicked", NULL);
+}
+
+
+/**
+ * Add a new photo to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Photo
+ */
+EAPI Evas_Object *
+elm_photo_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Object *icon;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "photo");
+   elm_widget_type_set(obj, "photo");
+   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, EINA_FALSE);
+
+   wd->frm = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->frm, "photo", "base", "default");
+   elm_widget_resize_object_set(obj, wd->frm);
+
+   wd->img = _els_smart_icon_add(e);
+   _els_smart_icon_scale_up_set(wd->img, 1);
+   _els_smart_icon_scale_down_set(wd->img, 1);
+   _els_smart_icon_smooth_scale_set(wd->img, 1);
+   _els_smart_icon_fill_inside_set(wd->img, 0);
+   _els_smart_icon_scale_size_set(wd->img, 0);
+   wd->fill = EINA_FALSE;
+   _els_smart_icon_scale_set(wd->img, 
+                             elm_widget_scale_get(obj) * _elm_config->scale);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
+                                 _mouse_up, obj);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_DOWN,
+                                 _mouse_down, obj);
+   evas_object_repeat_events_set(wd->img, 1);
+   edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
+   evas_object_show(wd->img);
+   elm_widget_sub_object_add(obj, wd->img);
+
+   wd->longtimer = NULL;
+
+   icon = _els_smart_icon_object_get(wd->img);
+   evas_object_event_callback_add(icon, EVAS_CALLBACK_MOVE,
+                                 _icon_move_resize, obj);
+   evas_object_event_callback_add(icon, EVAS_CALLBACK_RESIZE,
+                                 _icon_move_resize, obj);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the file that will be used as photo
+ *
+ * @param obj The photo object
+ * @param file The path to file that will be used as photo
+ *
+ * @return (1 = success, 0 = error)
+ *
+ * @ingroup Photo
+ */
+EAPI Eina_Bool
+elm_photo_file_set(Evas_Object *obj, const char *file)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return EINA_FALSE;
+   if (!_els_smart_icon_file_key_set(wd->img, file, NULL))
+     return EINA_FALSE;
+
+   _sizing_eval(obj);
+   return EINA_TRUE;
+}
+
+/**
+ * Set the size that will be used on the photo
+ *
+ * @param obj The photo object
+ * @param size The size that the photo will be
+ *
+ * @ingroup Photo
+ */
+EAPI void
+elm_photo_size_set(Evas_Object *obj, int size)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->size = (size > 0) ? size : 0;
+
+   _els_smart_icon_scale_size_set(wd->img, wd->size);
+
+   _sizing_eval(obj);
+}
+
+/**
+ * Set if the photo should be completely visible or not.
+ *
+ * @param obj The photo object
+ * @param fill if true the photo will be completely visible
+ *
+ * @ingroup Photo
+ */
+EAPI void
+elm_photo_fill_inside_set(Evas_Object *obj, Eina_Bool fill)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   _els_smart_icon_fill_inside_set(wd->img, fill);
+   wd->fill = fill;
+   _sizing_eval(obj);
+}
+
+/**
+ * Set editability of the photo.
+ *
+ * An editable photo can be dragged to or from, and can be cut or pasted too.
+ * Note that pasting an image or dropping an item on the image will delete the
+ * existing content.
+ *
+ * @param obj The photo object.
+ * @param set To set of clear editablity.
+ */
+EAPI void
+elm_photo_editable_set(Evas_Object *obj, Eina_Bool set)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;;
+   _els_smart_icon_edit_set(wd->img, set, obj);
+}
+
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/src/lib/elm_photocam.c b/src/lib/elm_photocam.c
new file mode 100644 (file)
index 0000000..78042ad
--- /dev/null
@@ -0,0 +1,1780 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Photocam Photocam
+ *
+ * This is a widget specifically for displaying high-resolution digital
+ * camera photos giving speedy feedback (fast load), low memory footprint
+ * and zooming and panning as well as fitting logic. It is entirely focused
+ * on jpeg images, and takes advantage of properties of the jpeg format (via
+ * evas loader features in the jpeg loader).
+ * 
+ * Signals that you can add callbacks for are:
+ *
+ * clicked - This is called when a user has clicked the photo without dragging
+ * around.
+ * 
+ * press - This is called when a user has pressed down on the photo.
+ * 
+ * longpressed - This is called when a user has pressed down on the photo for
+ * a long time without dragging around.
+ * 
+ * clicked,double - This is called when a user has double-clicked the photo.
+ * 
+ * load - Photo load begins.
+ * 
+ * loaded - This is called when the image file load is complete for the first
+ * view (low resolution blurry version).
+ *
+ * load,details - Photo detailed data load begins.
+ * 
+ * loaded,details - This is called when the image file load is complete for the
+ * detailed image data (full resolution needed).
+ *
+ * zoom,start - Zoom animation started.
+ * 
+ * zoom,stop - Zoom animation stopped.
+ * 
+ * zoom,change - Zoom changed when using an auto zoom mode.
+ * 
+ * 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
+ * 
+ * ---
+ * 
+ * TODO (maybe - optional future stuff):
+ * 
+ * 1. wrap photo in theme edje so u can have styling around photo (like white
+ *    photo bordering).
+ * 2. exif handling
+ * 3. rotation flags in exif handling (nasty! should have rot in evas)
+ *
+ */
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Pan Pan;
+typedef struct _Grid Grid;
+typedef struct _Grid_Item Grid_Item;
+
+struct _Grid_Item
+{
+   Widget_Data *wd;
+   Evas_Object *img;
+   struct 
+     {
+        int x, y, w, h;
+     } src, out;
+   Eina_Bool want : 1;
+   Eina_Bool have : 1;
+};
+
+struct _Grid
+{
+   int tsize; // size of tile (tsize x tsize pixels)
+   int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8)
+   int iw, ih; // size of image in pixels
+   int w, h; // size of grid image in pixels (represented by grid)
+   int gw, gh; // size of grid in tiles
+   Grid_Item *grid; // the grid (gw * gh items)
+   Eina_Bool dead : 1; // old grid. will die as soon as anim is over
+};
+
+struct _Widget_Data
+{
+   Evas_Object *obj;
+   Evas_Object *scr;
+   Evas_Object *pan_smart;
+   Pan *pan;
+   Evas_Coord pan_x, pan_y, minw, minh;
+
+   double zoom;
+   Elm_Photocam_Zoom_Mode mode;
+   const char *file;
+   
+   Ecore_Job *calc_job;
+   Ecore_Timer *scr_timer;
+   Ecore_Timer *long_timer;
+   Ecore_Animator *zoom_animator;
+   double t_start, t_end;
+   struct 
+     {
+        int imw, imh;
+        int w, h;
+        int ow, oh, nw, nh;
+        struct 
+          {
+             double x, y;
+          } spos;
+     } size;
+   struct
+     {
+       Eina_Bool show : 1;
+       Evas_Coord x, y ,w ,h;
+     } show;
+   int tsize;
+   Evas_Object *img; // low res version of image (scale down == 8)
+   int nosmooth;
+   int preload_num;
+   Eina_List *grids;
+   Eina_Bool main_load_pending : 1;
+   Eina_Bool resized : 1;
+   Eina_Bool longpressed : 1;
+   Eina_Bool on_hold : 1;
+   Eina_Bool paused : 1;
+};
+
+struct _Pan
+{
+   Evas_Object_Smart_Clipped_Data __clipped_data;
+   Widget_Data *wd;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+//static void _show_region_hook(void *data, Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _calc_job(void *data);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
+                             Evas_Callback_Type type, void *event_info);
+static void grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
+static void grid_clear(Evas_Object *obj, Grid *g);
+static Grid *grid_create(Evas_Object *obj);
+static void grid_load(Evas_Object *obj, Grid *g);
+
+static int
+nearest_pow2(int num)
+{
+   unsigned int n = num - 1;
+   n |= n >> 1;
+   n |= n >> 2;
+   n |= n >> 4;
+   n |= n >> 8;
+   n |= n >> 16;
+   return n + 1;
+}
+
+static void
+img_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord ax, ay, gw, gh;
+   if (!wd) return;
+   ax = 0;
+   ay = 0;
+   gw = wd->size.w;
+   gh = wd->size.h;
+   if (ow > gw) ax = (ow - gw) / 2;
+   if (oh > gh) ay = (oh - gh) / 2;
+   evas_object_move(wd->img, ox + 0 - px + ax, oy + 0 - py + ay);
+   evas_object_resize(wd->img, gw, gh);
+
+   if (wd->show.show)
+     {
+       wd->show.show = EINA_FALSE;
+       elm_smart_scroller_child_region_show(wd->scr, wd->show.x, wd->show.y, wd->show.w, wd->show.h);
+     }
+}
+
+static void
+grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord ax, ay, gw, gh, tx, ty;
+   int x, y;
+   if (!wd) return;
+   ax = 0;
+   ay = 0;
+   gw = wd->size.w;
+   gh = wd->size.h;
+   if (ow > gw) ax = (ow - gw) / 2;
+   if (oh > gh) ay = (oh - gh) / 2;
+   for (y = 0; y < g->gh; y++)
+     {
+        for (x = 0; x < g->gw; x++)
+          {
+             int tn, xx, yy, ww, hh;
+             
+             tn = (y * g->gw) + x;
+             xx = g->grid[tn].out.x;
+             yy = g->grid[tn].out.y;
+             ww = g->grid[tn].out.w;
+             hh = g->grid[tn].out.h;
+             if ((gw != g->w) && (g->w > 0))
+               {
+                  tx = xx;
+                  xx = (gw * xx) / g->w;
+                  ww = ((gw * (tx + ww)) / g->w) - xx;
+               }
+             if ((gh != g->h) && (g->h > 0))
+               {
+                  ty = yy;
+                  yy = (gh * yy) / g->h;
+                  hh = ((gh * (ty + hh)) / g->h) - yy;
+               }
+             evas_object_move(g->grid[tn].img,
+                              ox + xx - px + ax,
+                              oy + yy - py + ay);
+             evas_object_resize(g->grid[tn].img, ww, hh);
+          }
+     }
+}
+
+static void
+grid_clear(Evas_Object *obj, Grid *g)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int x, y;
+   if (!wd) return;
+   if (!g->grid) return;
+   for (y = 0; y < g->gh; y++)
+     {
+        for (x = 0; x < g->gw; x++)
+          {
+             int tn;
+             
+             tn = (y * g->gw) + x;
+             evas_object_del(g->grid[tn].img);
+             if (g->grid[tn].want)
+               {
+                  wd->preload_num--;
+                  if (!wd->preload_num)
+                    {
+                       edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                                               "elm,state,busy,stop", "elm");
+                       evas_object_smart_callback_call(obj, "loaded,detail", NULL);
+                    }
+               }
+          }
+     }
+   free(g->grid);
+   g->grid = NULL;
+   g->gw = 0;
+   g->gh = 0;
+}
+
+static void
+_tile_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   Grid_Item *git = data;
+
+   if (git->want)
+     {
+        git->want = 0;
+        evas_object_show(git->img);
+        git->have = 1;
+        git->wd->preload_num--;
+        if (!git->wd->preload_num)
+          {
+             edje_object_signal_emit(elm_smart_scroller_edje_object_get(git->wd->scr),
+                                     "elm,state,busy,stop", "elm");
+             evas_object_smart_callback_call(git->wd->obj, "loaded,detail", NULL);
+          }
+     }
+}
+
+static int
+grid_zoom_calc(double zoom)
+{
+   int z = zoom;
+   if (z < 1) z = 1;
+   return nearest_pow2(z);
+}
+
+static Grid *
+grid_create(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int x, y;
+   Grid *g;
+   
+   if (!wd) return NULL;
+   g = calloc(1, sizeof(Grid));
+   
+   g->zoom = grid_zoom_calc(wd->zoom);
+   g->tsize = wd->tsize;
+   g->iw = wd->size.imw;
+   g->ih = wd->size.imh;
+   
+   g->w = g->iw / g->zoom;
+   g->h = g->ih / g->zoom;
+   if (g->zoom >= 8) return NULL;
+   g->gw = (g->w + g->tsize - 1) / g->tsize;
+   g->gh = (g->h + g->tsize - 1) / g->tsize;
+   g->grid = calloc(1, sizeof(Grid_Item) * g->gw * g->gh);
+   if (!g->grid)
+     {
+        g->gw = 0;
+        g->gh = 0;
+        return g;
+     }
+   for (y = 0; y < g->gh; y++)
+     {
+        for (x = 0; x < g->gw; x++)
+          {
+             int tn;
+             
+             tn = (y * g->gw) + x;
+             g->grid[tn].src.x = x * g->tsize;
+             if (x == (g->gw - 1))
+               g->grid[tn].src.w = g->w - ((g->gw - 1) * g->tsize);
+             else
+               g->grid[tn].src.w = g->tsize;
+             g->grid[tn].src.y = y * g->tsize;
+             if (y == (g->gh - 1))
+               g->grid[tn].src.h = g->h - ((g->gh - 1) * g->tsize);
+             else
+               g->grid[tn].src.h = g->tsize;
+             
+             g->grid[tn].out.x = g->grid[tn].src.x;
+             g->grid[tn].out.y = g->grid[tn].src.y;
+             g->grid[tn].out.w = g->grid[tn].src.w;
+             g->grid[tn].out.h = g->grid[tn].src.h;
+             
+             g->grid[tn].wd = wd;
+             g->grid[tn].img = 
+               evas_object_image_add(evas_object_evas_get(obj));
+             evas_object_image_scale_hint_set
+               (g->grid[tn].img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
+             evas_object_pass_events_set(g->grid[tn].img, EINA_TRUE);
+             evas_object_smart_member_add(g->grid[tn].img, 
+                                          wd->pan_smart);
+             elm_widget_sub_object_add(obj, g->grid[tn].img);
+             evas_object_image_filled_set(g->grid[tn].img, 1);
+             evas_object_event_callback_add(g->grid[tn].img, 
+                                            EVAS_CALLBACK_IMAGE_PRELOADED,
+                                            _tile_preloaded, 
+                                            &(g->grid[tn]));
+          }
+     }
+   return g;
+}
+
+static void
+grid_load(Evas_Object *obj, Grid *g)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int x, y;
+   Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, gw, gh, tx, ty;
+   if (!wd) return;
+   evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
+   evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh);
+   gw = wd->size.w;
+   gh = wd->size.h;
+   for (y = 0; y < g->gh; y++)
+     {
+        for (x = 0; x < g->gw; x++)
+          {
+             int tn, xx, yy, ww, hh;
+             Eina_Bool visible = EINA_FALSE;
+             
+             tn = (y * g->gw) + x;
+             xx = g->grid[tn].out.x;
+             yy = g->grid[tn].out.y;
+             ww = g->grid[tn].out.w;
+             hh = g->grid[tn].out.h;
+             if ((gw != g->w) && (g->w > 0))
+               {
+                  tx = xx;
+                  xx = (gw * xx) / g->w;
+                  ww = ((gw * (tx + ww)) / g->w) - xx;
+               }
+             if ((gh != g->h) && (g->h > 0))
+               {
+                  ty = yy;
+                  yy = (gh * yy) / g->h;
+                  hh = ((gh * (ty + hh)) / g->h) - yy;
+               }
+             if (ELM_RECTS_INTERSECT(xx - wd->pan_x + ox, 
+                                     yy  - wd->pan_y + oy,
+                                     ww, hh,
+                                     cvx, cvy, cvw, cvh))
+               visible = 1;
+             if ((visible) && (!g->grid[tn].have) && (!g->grid[tn].want))
+               {
+                  g->grid[tn].want = 1;
+                  evas_object_hide(g->grid[tn].img);
+                  evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
+                  evas_object_image_load_scale_down_set(g->grid[tn].img, g->zoom);
+                  evas_object_image_load_region_set(g->grid[tn].img,
+                                                    g->grid[tn].src.x,
+                                                    g->grid[tn].src.y,
+                                                    g->grid[tn].src.w,
+                                                    g->grid[tn].src.h);
+                  evas_object_image_file_set(g->grid[tn].img, wd->file, NULL); 
+                  evas_object_image_preload(g->grid[tn].img, 0);
+                  wd->preload_num++;
+                  if (wd->preload_num == 1)
+                    {
+                       edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                                               "elm,state,busy,start", "elm");
+                       evas_object_smart_callback_call(obj, "load,detail", NULL);
+                    }
+               }
+             else if ((g->grid[tn].want) && (!visible))
+               {
+                  wd->preload_num--;
+                  if (!wd->preload_num)
+                    {
+                       edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                                               "elm,state,busy,stop", "elm");
+                       evas_object_smart_callback_call(obj, "loaded,detail", NULL);
+                    }
+                  g->grid[tn].want = 0;
+                  evas_object_hide(g->grid[tn].img);
+                  evas_object_image_preload(g->grid[tn].img, 1);
+                  evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
+               }
+             else if ((g->grid[tn].have) && (!visible))
+               {
+                  g->grid[tn].have = 0;
+                  evas_object_hide(g->grid[tn].img);
+                  evas_object_image_preload(g->grid[tn].img, 1);
+                  evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
+               }
+          }
+     }
+}
+
+static void
+grid_clearall(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Grid *g;
+   if (!wd) return;
+   EINA_LIST_FREE(wd->grids, g)
+     {
+        grid_clear(obj, g);
+        free(g);
+     }
+}
+
+static void
+_smooth_update(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int x, y;
+   Eina_List *l;
+   Grid *g;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->grids, l, g)
+     {
+        for (y = 0; y < g->gh; y++)
+          {
+             for (x = 0; x < g->gw; x++)
+               {
+                  int tn;
+                  
+                  tn = (y * g->gw) + x;
+                  evas_object_image_smooth_scale_set(g->grid[tn].img, (!wd->nosmooth));
+               }
+          }
+     }
+   evas_object_image_smooth_scale_set(wd->img, (!wd->nosmooth));
+}
+
+static void
+_grid_raise(Grid *g)
+{
+   int x, y;
+   
+   for (y = 0; y < g->gh; y++)
+     {
+        for (x = 0; x < g->gw; x++)
+          {
+             int tn;
+             
+             tn = (y * g->gw) + x;
+             evas_object_raise(g->grid[tn].img);
+          }
+     }
+}
+
+static Eina_Bool
+_scr_timeout(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->nosmooth--;
+   if (!wd->nosmooth) _smooth_update(data);
+   wd->scr_timer = NULL;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (!wd->scr_timer)
+     {
+        wd->nosmooth++;
+        if (wd->nosmooth == 1) _smooth_update(data);
+     }
+   if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
+   wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data);
+}
+
+static void
+_main_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *obj = data;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Grid *g;
+   if (!wd) return;
+   evas_object_show(wd->img);
+   wd->main_load_pending = 0;
+   g = grid_create(obj);
+   if (g)
+     {
+        wd->grids = eina_list_prepend(wd->grids, g);
+        grid_load(wd->obj, g);
+     }
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   evas_object_smart_callback_call(data, "loaded", NULL);
+   wd->preload_num--;
+   if (!wd->preload_num)
+     {
+        edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                                "elm,state,busy,stop", "elm");
+        evas_object_smart_callback_call(obj, "loaded,detail", NULL);
+     }
+}
+
+static Eina_Bool
+zoom_do(Evas_Object *obj, double t)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord xx, yy, ow, oh;
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->size.w = (wd->size.ow * (1.0 - t)) + (wd->size.nw * t);
+   wd->size.h = (wd->size.oh * (1.0 - t)) + (wd->size.nh * t);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh);
+   xx = (wd->size.spos.x * wd->size.w) - (ow / 2);
+   yy = (wd->size.spos.y * wd->size.h) - (oh / 2);
+   if (xx < 0) xx = 0;
+   else if (xx > (wd->size.w - ow)) xx = wd->size.w - ow;
+   if (yy < 0) yy = 0;
+   else if (yy > (wd->size.h - oh)) yy = wd->size.h - oh;
+
+   wd->show.show = EINA_TRUE;
+   wd->show.x = xx;
+   wd->show.y = yy;
+   wd->show.w = ow;
+   wd->show.h = oh;
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   if (t >= 1.0)
+     {
+        Eina_List *l, *l_next;
+        Grid *g;
+        
+        EINA_LIST_FOREACH_SAFE(wd->grids, l, l_next, g)
+          {
+             if (g->dead)
+               {
+                  wd->grids = eina_list_remove_list(wd->grids, l);
+                  grid_clear(obj, g);
+                  free(g);
+               }
+          }
+        return ECORE_CALLBACK_CANCEL;
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+
+static Eina_Bool
+_zoom_anim(void *data)
+{
+   Evas_Object *obj = data;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double t;
+   Eina_Bool go;
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   t = ecore_loop_time_get();
+   if (t >= wd->t_end)
+     t = 1.0;
+   else if (wd->t_end > wd->t_start)
+     t = (t - wd->t_start) / (wd->t_end - wd->t_start);
+   else
+     t = 1.0;
+   t = 1.0 - t;
+   t = 1.0 - (t * t);
+   go = zoom_do(obj, t);
+   if (!go)
+     {
+        wd->nosmooth--;
+        if (!wd->nosmooth) _smooth_update(data);
+        wd->zoom_animator = NULL;
+        evas_object_smart_callback_call(obj, "zoom,stop", NULL);
+     }
+   return go;
+}
+
+static void
+_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+//   Evas_Event_Mouse_Move *ev = event_info;
+   if (!wd) return;
+}
+
+static Eina_Bool
+_long_press(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->long_timer = NULL;
+   wd->longpressed = EINA_TRUE;
+   evas_object_smart_callback_call(data, "longpressed", NULL);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Down *ev = event_info;
+   if (!wd) return;
+   if (ev->button != 1) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
+   else wd->on_hold = EINA_FALSE;
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     evas_object_smart_callback_call(data, "clicked,double", NULL);
+   else
+     evas_object_smart_callback_call(data, "press", NULL);
+   wd->longpressed = EINA_FALSE;
+   if (wd->long_timer) ecore_timer_del(wd->long_timer);
+   wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
+}
+   
+static void
+_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Up *ev = event_info;
+   if (!wd) return;
+   if (ev->button != 1) return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
+   else wd->on_hold = EINA_FALSE;
+   if (wd->long_timer)
+     {
+        ecore_timer_del(wd->long_timer);
+        wd->long_timer = NULL;
+     }
+   if (!wd->on_hold)
+     evas_object_smart_callback_call(data, "clicked", NULL);
+   wd->on_hold = EINA_FALSE;
+}
+   
+static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL;
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Grid *g;
+   if (!wd) return;
+   EINA_LIST_FREE(wd->grids, g)
+     {
+        if (g->grid) free(g->grid);
+        free(g);
+     }
+   evas_object_del(wd->pan_smart);
+   wd->pan_smart = NULL;
+   if (wd->file) eina_stringshare_del(wd->file);
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
+   if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
+   if (wd->long_timer) ecore_timer_del(wd->long_timer);
+   free(wd);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->obj, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->obj, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->obj, EINA_FALSE);
+     }
+}
+
+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, "photocam", "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);
+   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 minw = -1, minh = -1, maxw = -1, maxh = -1;
+   if (!wd) return;
+//   evas_object_size_hint_min_get(wd->scr, &minw, &minh);
+   evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
+//   minw = -1;
+//   minh = -1;
+//   if (wd->mode != ELM_LIST_LIMIT) minw = -1;
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_calc_job(void *data)
+{
+   Widget_Data *wd = data;
+   Evas_Coord minw, minh;
+   if (!wd) return;
+   minw = wd->size.w;
+   minh = wd->size.h;
+   if (wd->resized)
+     {
+        wd->resized = 0;
+        if (wd->mode != ELM_PHOTOCAM_ZOOM_MODE_MANUAL)
+          {
+             double tz = wd->zoom;
+             wd->zoom = 0.0;
+             elm_photocam_zoom_set(wd->obj, tz);
+          }
+     }
+   if ((minw != wd->minw) || (minh != wd->minh))
+     {
+        wd->minw = minw;
+        wd->minh = minh;
+        evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
+        _sizing_eval(wd->obj);
+     }
+   wd->calc_job = NULL;
+   evas_object_smart_changed(wd->pan_smart);
+}
+
+static void
+_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   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 (!sd) return;
+   if (x) *x = sd->wd->pan_x;
+   if (y) *y = sd->wd->pan_y;
+}
+
+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);
+   ow = sd->wd->minw - ow;
+   if (ow < 0) ow = 0;
+   oh = sd->wd->minh - oh;
+   if (oh < 0) oh = 0;
+   if (x) *x = ow;
+   if (y) *y = oh;
+}
+
+static void
+_pan_min_get(Evas_Object *obj __UNUSED__, Evas_Coord *x, Evas_Coord *y)
+{
+   if (x) *x = 0;
+   if (y) *y = 0;
+}
+
+static void
+_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (w) *w = sd->wd->minw;
+   if (h) *h = sd->wd->minh;
+}
+
+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);
+   if (!cd) return;
+   sd = calloc(1, sizeof(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_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   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 ((ow == w) && (oh == h)) return;
+   sd->wd->resized = 1;
+   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 ox, oy, ow, oh;
+   Eina_List *l;
+   Grid *g;
+   if (!sd) return;
+   evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
+   img_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+   EINA_LIST_FOREACH(sd->wd->grids, l, g)
+     {
+        grid_load(sd->wd->obj, g);
+        grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+     }
+}
+
+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_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "scroll,anim,start", NULL);
+}
+
+static void
+_scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "scroll,anim,stop", NULL);
+}
+
+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);
+}
+
+static Eina_Bool 
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
+                             Evas_Callback_Type type, void *event_info)
+{
+   double zoom;
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+
+   Evas_Coord x = 0;
+   Evas_Coord y = 0;
+   Evas_Coord step_x = 0;
+   Evas_Coord step_y = 0;
+   Evas_Coord v_w = 0;
+   Evas_Coord v_h = 0;
+   Evas_Coord page_x = 0;
+   Evas_Coord page_y = 0;
+
+   elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
+   elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
+   elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
+
+   if ((!strcmp(ev->keyname, "Left")) || 
+       (!strcmp(ev->keyname, "KP_Left")))
+     {
+        x -= step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Right")) || 
+            (!strcmp(ev->keyname, "KP_Right")))
+     {
+        x += step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Up"))  || 
+            (!strcmp(ev->keyname, "KP_Up")))
+     {
+        y -= step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Down")) || 
+            (!strcmp(ev->keyname, "KP_Down")))
+     {
+        y += step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Prior")) || 
+            (!strcmp(ev->keyname, "KP_Prior")))
+     {
+        if (page_y < 0)
+           y -= -(page_y * v_h) / 100;
+        else
+           y -= page_y;
+     }
+   else if ((!strcmp(ev->keyname, "Next")) || 
+            (!strcmp(ev->keyname, "KP_Next")))
+     {
+        if (page_y < 0)
+           y += -(page_y * v_h) / 100;
+        else
+           y += page_y;
+     }
+   else if ((!strcmp(ev->keyname, "KP_Add")))
+     {
+        zoom = elm_photocam_zoom_get(obj);
+        zoom -= 0.5;
+        elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
+        elm_photocam_zoom_set(obj, zoom);
+        return EINA_TRUE;
+     } 
+   else if ((!strcmp(ev->keyname, "KP_Subtract")))
+     {
+        zoom = elm_photocam_zoom_get(obj);
+        zoom += 0.5;
+        elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
+        elm_photocam_zoom_set(obj, zoom);
+        return EINA_TRUE;
+     }
+   else return EINA_FALSE;
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   elm_smart_scroller_child_pos_set(wd->scr, x, y);
+
+   return EINA_TRUE;
+}
+
+/**
+ * Add a new Photocam object
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Photocam
+ */
+EAPI Evas_Object *
+elm_photocam_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord minw, minh;
+   static Evas_Smart *smart = NULL;
+   Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "photocam");
+   elm_widget_type_set(obj, "photocam");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_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, "photocam", "base", "default");
+   evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj);
+   evas_object_smart_callback_add(wd->scr, "drag", _scr, obj);
+   elm_widget_resize_object_set(obj, wd->scr);
+
+   evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
+   evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
+   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, bounce, bounce);
+
+   wd->obj = 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);
+   
+   if (!smart)
+     {
+       static Evas_Smart_Class sc;
+
+       evas_object_smart_clipped_smart_set(&_pan_sc);
+       sc = _pan_sc;
+       sc.name = "elm_photocam_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_min_get, _pan_child_size_get);
+
+   wd->zoom = 1;
+   wd->mode = ELM_PHOTOCAM_ZOOM_MODE_MANUAL;
+   
+   wd->tsize = 512;
+   
+   wd->img = evas_object_image_add(e);
+   evas_object_image_scale_hint_set(wd->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _mouse_down, obj);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
+                                  _mouse_up, obj);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _mouse_move, obj);
+   evas_object_image_scale_hint_set(wd->img, EVAS_IMAGE_SCALE_HINT_STATIC);
+   evas_object_smart_member_add(wd->img, wd->pan_smart);
+   elm_widget_sub_object_add(obj, wd->img);
+   evas_object_image_filled_set(wd->img, 1);
+   evas_object_event_callback_add(wd->img, EVAS_CALLBACK_IMAGE_PRELOADED,
+                                  _main_preloaded, obj);
+   
+   edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), 
+                             &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the photo file to be shown
+ *
+ * This sets (and shows) the specified file (with a relative or absolute path)
+ * and will return a load error (same error that
+ * evas_object_image_load_error_get() will return). The image will change and
+ * adjust its size at this point and begin a background load process for this
+ * photo that at some time in the future will be displayed at the full quality
+ * needed.
+ *
+ * @param obj The photocam object
+ * @param file The photo file
+ * @return The return error (see EVAS_LOAD_ERROR_NONE, EVAS_LOAD_ERROR_GENERIC etc.)
+ *
+ * @ingroup Photocam
+ */
+EAPI Evas_Load_Error
+elm_photocam_file_set(Evas_Object *obj, const char *file)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EVAS_LOAD_ERROR_NONE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int w, h;
+   if (!wd) return EVAS_LOAD_ERROR_GENERIC;
+   if (!eina_stringshare_replace(&wd->file, file)) return EVAS_LOAD_ERROR_NONE;
+   evas_object_hide(wd->img);
+   evas_object_image_smooth_scale_set(wd->img, (wd->nosmooth == 0));
+   evas_object_image_file_set(wd->img, NULL, NULL);
+   evas_object_image_load_scale_down_set(wd->img, 0);
+   evas_object_image_file_set(wd->img, wd->file, NULL);
+   evas_object_image_size_get(wd->img, &w, &h);
+   wd->size.imw = w;
+   wd->size.imh = h;
+   wd->size.w = wd->size.imw / wd->zoom;
+   wd->size.h = wd->size.imh / wd->zoom;
+   if (wd->zoom_animator)
+     {
+        wd->nosmooth--;
+        if (wd->nosmooth == 0) _smooth_update(obj);
+        ecore_animator_del(wd->zoom_animator);
+        wd->zoom_animator = NULL;
+     }
+   evas_object_image_file_set(wd->img, NULL, NULL);
+   evas_object_image_load_scale_down_set(wd->img, 8);
+   evas_object_image_file_set(wd->img, wd->file, NULL);
+   evas_object_image_preload(wd->img, 0);
+   wd->main_load_pending = 1;
+   grid_clearall(obj);
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   evas_object_smart_callback_call(obj, "load", NULL);
+   wd->preload_num++;
+   if (wd->preload_num == 1)
+     {
+        edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+                                "elm,state,busy,start", "elm");
+        evas_object_smart_callback_call(obj, "load,detail", NULL);
+     }
+     {
+        double tz = wd->zoom;
+        wd->zoom = 0.0;
+        elm_photocam_zoom_set(wd->obj, tz);
+     }
+   return evas_object_image_load_error_get(wd->img);
+}
+
+/*
+ * Returns the path of the current image file
+ *
+ * @param obj The photocam object
+ * @return Returns the path 
+ *
+ * @ingroup Photocam
+ */
+EAPI const char *
+elm_photocam_file_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->file;
+}
+
+/**
+ * Set the zoom level of the photo
+ *
+ * This sets the zoom level. 1 will be 1:1 pixel for pixel. 2 will be 2:1
+ * (that is 2x2 photo pixels will display as 1 on-screen pixel). 4:1 will be
+ * 4x4 photo pixels as 1 screen pixel, and so on. The @p zoom parameter must
+ * be greater than 0. It is usggested to stick to powers of 2. (1, 2, 4, 8,
+ * 16, 32, etc.). 
+ *
+ * @param obj The photocam object
+ * @param zoom The zoom level to set
+ *
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_zoom_set(Evas_Object *obj, double zoom)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *l;
+   Grid *g, *g_zoom = NULL;
+   Evas_Coord pw, ph, rx, ry, rw, rh;
+   int z;
+   int zoom_changed = 0, started = 0;
+   Ecore_Animator *an;
+   if (!wd) return;
+   if (zoom <= (1.0 / 256.0)) zoom = (1.0 / 256.0);
+   if (zoom == wd->zoom) return;
+   wd->zoom = zoom;
+   wd->size.ow = wd->size.w;
+   wd->size.oh = wd->size.h;
+   elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+   if ((rw <= 0) || (rh <= 0)) return;
+
+   if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_MANUAL)
+     {
+        wd->size.nw = (double)wd->size.imw / wd->zoom;
+        wd->size.nh = (double)wd->size.imh / wd->zoom;
+     }
+   else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT)
+     {
+        if ((wd->size.imw < 1) || (wd->size.imh < 1))
+          {
+             wd->size.nw = 0;
+             wd->size.nw = 0;
+          }
+        else
+          {
+             ph = (wd->size.imh * rw) / wd->size.imw;
+             if (ph > rh)
+               {
+                  pw = (wd->size.imw * rh) / wd->size.imh;
+                  ph = rh;
+               }
+             else
+               {
+                  pw = rw;
+               }
+             if (wd->size.imw > wd->size.imh)
+               z = wd->size.imw / pw;
+             else
+               z = wd->size.imh / ph;
+             if      (z >= 8) z = 8;
+             else if (z >= 4) z = 4;
+             else if (z >= 2) z = 2;
+             else             z = 1;
+             if (z != wd->zoom) zoom_changed = 1;
+             wd->zoom = z;
+             wd->size.nw = pw;
+             wd->size.nh = ph;
+          }
+     }
+   else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL)
+     {
+        if ((wd->size.imw < 1) || (wd->size.imh < 1))
+          {
+             wd->size.nw = 0;
+             wd->size.nw = 0;
+          }
+        else
+          {
+             ph = (wd->size.imh * rw) / wd->size.imw;
+             if (ph < rh)
+               {
+                  pw = (wd->size.imw * rh) / wd->size.imh;
+                  ph = rh;
+               }
+             else
+               {
+                  pw = rw;
+               }
+             if (wd->size.imw > wd->size.imh)
+               z = wd->size.imw / pw;
+             else
+               z = wd->size.imh / ph;
+             if      (z >= 8) z = 8;
+             else if (z >= 4) z = 4;
+             else if (z >= 2) z = 2;
+             else             z = 1;
+             if (z != wd->zoom) zoom_changed = 1;
+             wd->zoom = z;
+             wd->size.nw = pw;
+             wd->size.nh = ph;
+          }
+     }
+   if (wd->main_load_pending)
+     {
+        wd->size.w = wd->size.nw;
+        wd->size.h = wd->size.nh;
+        goto done;
+     }
+   EINA_LIST_FOREACH(wd->grids, l, g)
+     {
+        if (g->zoom == grid_zoom_calc(wd->zoom))
+          {
+             wd->grids = eina_list_remove(wd->grids, g);
+             wd->grids = eina_list_prepend(wd->grids, g);
+             _grid_raise(g);
+             goto done;
+          }
+     }
+   g = grid_create(obj);
+   if (g)
+     {
+        if (eina_list_count(wd->grids) > 1)
+          {
+             g_zoom = eina_list_last(wd->grids)->data;
+             wd->grids = eina_list_remove(wd->grids, g_zoom);
+             grid_clear(obj, g_zoom);
+             free(g_zoom);
+             EINA_LIST_FOREACH(wd->grids, l, g_zoom)
+               {
+                  g_zoom->dead = 1;
+               }
+          }
+        wd->grids = eina_list_prepend(wd->grids, g);
+     }
+   else
+     {
+        EINA_LIST_FREE(wd->grids, g)
+          {
+             grid_clear(obj, g);
+             free(g);
+          }
+     }
+   done:
+   wd->t_start = ecore_loop_time_get();
+   wd->t_end = wd->t_start + _elm_config->zoom_friction;
+   if ((wd->size.w > 0) && (wd->size.h > 0))
+     {
+        wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.w;
+        wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.h;
+     }
+   else
+     {
+        wd->size.spos.x = 0.5;
+        wd->size.spos.y = 0.5;
+     }
+   if (rw > wd->size.w) wd->size.spos.x = 0.5;
+   if (rh > wd->size.h) wd->size.spos.y = 0.5;
+   if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0;
+   if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0;
+   if (wd->paused)
+     {
+        zoom_do(obj, 1.0);
+     }
+   else
+     {
+        if (!wd->zoom_animator)
+          {
+             wd->zoom_animator = ecore_animator_add(_zoom_anim, obj);
+             wd->nosmooth++;
+             if (wd->nosmooth == 1) _smooth_update(obj);
+             started = 1;
+          }
+     }
+   an = wd->zoom_animator;
+   if (an)
+     {
+        if (!_zoom_anim(obj))
+          {
+             ecore_animator_del(an);
+             an = NULL;
+          }
+     }
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+   if (!wd->paused)
+     {
+        if (started)
+          evas_object_smart_callback_call(obj, "zoom,start", NULL);
+        if (!an)
+          evas_object_smart_callback_call(obj, "zoom,stop", NULL);
+     }
+   if (zoom_changed)
+     evas_object_smart_callback_call(obj, "zoom,change", NULL);
+}
+
+/**
+ * Get the zoom level of the photo
+ *
+ * This returns the current zoom level of the photocam object. Note that if
+ * you set the fill mode to other than ELM_PHOTOCAM_ZOOM_MODE_MANUAL
+ * (which is the default), the zoom level may be changed at any time by the
+ * photocam object itself to account for photo size and photocam viewpoer size
+ *
+ * @param obj The photocam object
+ * @return The current zoom level
+ *
+ * @ingroup Photocam
+ */
+EAPI double
+elm_photocam_zoom_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 1.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 1.0;
+   return wd->zoom;
+}
+
+/**
+ * Set the zoom mode
+ *
+ * This sets the zoom mode to manual or one of several automatic levels.
+ * Manual (ELM_PHOTOCAM_ZOOM_MODE_MANUAL) means that zoom is set manually by
+ * elm_photocam_zoom_set() and will stay at that level until changed by code
+ * or until zoom mode is changed. This is the default mode.
+ * The Automatic modes will allow the photocam object to automatically
+ * adjust zoom mode based on properties. ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT) will
+ * adjust zoom so the photo fits EXACTLY inside the scroll frame with no pixels
+ * outside this area. ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL will be similar but
+ * ensure no pixels within the frame are left unfilled.
+ *
+ * @param obj The photocam object
+ * @param mode The desired mode
+ *
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_zoom_mode_set(Evas_Object *obj, Elm_Photocam_Zoom_Mode mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->mode == mode) return;
+   wd->mode = mode;
+     {
+        double tz = wd->zoom;
+        wd->zoom = 0.0;
+        elm_photocam_zoom_set(wd->obj, tz);
+     }
+}
+
+/**
+ * Get the zoom mode
+ *
+ * This gets the current zoom mode of the photocam object
+ *
+ * @param obj The photocam object
+ * @return The current zoom mode
+ *
+ * @ingroup Photocam
+ */
+EAPI Elm_Photocam_Zoom_Mode
+elm_photocam_zoom_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_PHOTOCAM_ZOOM_MODE_LAST;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_PHOTOCAM_ZOOM_MODE_LAST;
+   return wd->mode;
+}
+
+/**
+ * Get the current image pixel width and height
+ *
+ * This gets the current photo pixel width and height (for the original).
+ * The size will be returned in the integers @p w and @p h that are pointed
+ * to.
+ *
+ * @param obj The photocam object
+ * @param w A pointer to the width return
+ * @param h A pointer to the height return
+ *
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_image_size_get(const Evas_Object *obj, int *w, int *h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (w) *w = wd->size.imw;
+   if (h) *h = wd->size.imh;
+}
+
+/**
+ * Get the current area of the image that is currently shown
+ * 
+ * This gets the region 
+ * 
+ */
+EAPI void
+elm_photocam_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord sx, sy, sw, sh;
+   if (!wd) return;
+   elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
+   if (wd->size.w > 0)
+     {
+        if (x)
+          {
+             *x = (wd->size.imw * sx) / wd->size.w;
+             if (*x > wd->size.imw) *x = wd->size.imw;
+             else if (*x < 0) *x = 0;
+          }
+        if (w)
+          {
+             *w = (wd->size.imw * sw) / wd->size.w;
+             if (*w > wd->size.imw) *w = wd->size.imw;
+             else if (*w < 0) *w = 0;
+          }
+     }
+   else
+     {
+       if (x) *x = 0;
+       if (w) *w = 0;
+     }
+
+   if (wd->size.h > 0)
+     {
+        if (y)
+          {
+             *y = (wd->size.imh * sy) / wd->size.h;
+             if (*y > wd->size.imh) *y = wd->size.imh;
+             else if (*y < 0) *y = 0;
+          }
+        if (h)
+          {
+             *h = (wd->size.imh * sh) / wd->size.h;
+             if (*h > wd->size.imh) *h = wd->size.imh;
+             else if (*h < 0) *h = 0;
+          }
+     }
+   else
+     {
+       if (y) *y = 0;
+       if (h) *h = 0;
+     }
+}
+
+/**
+ * Set the viewed portion of the image
+ *
+ * This sets the region of the image to be viewed
+ *
+ * @param obj The photocam object
+ * @param x X-coordinate of region in image original pixels
+ * @param y Y-coordinate of region in image original pixels
+ * @param w Width of region in image original pixels
+ * @param h Height of region in image original pixels
+ *
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_image_region_show(Evas_Object *obj, int x, int y, int w, int h __UNUSED__)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int rx, ry, rw, rh;
+   if (!wd) return;
+   if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
+   rx = (x * wd->size.w) / wd->size.imw;
+   ry = (y * wd->size.h) / wd->size.imh;
+   rw = (w * wd->size.w) / wd->size.imw;
+   rh = (w * wd->size.h) / wd->size.imh;
+   if (rw < 1) rw = 1;
+   if (rh < 1) rh = 1;
+   if ((rx + rw) > wd->size.w) rx = wd->size.w - rw; 
+   if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
+   if (wd->zoom_animator)
+     {
+        wd->nosmooth--;
+        ecore_animator_del(wd->zoom_animator);
+        wd->zoom_animator = NULL;
+        zoom_do(obj, 1.0);
+        evas_object_smart_callback_call(obj, "zoom,stop", NULL);
+     }
+   elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh);
+}
+
+/**
+ * Bring in the viewed portion of the image
+ *
+ * This brings in the region of the image over time
+ *
+ * @param obj The photocam object
+ * @param x X-coordinate of region in image original pixels
+ * @param y Y-coordinate of region in image original pixels
+ * @param w Width of region in image original pixels
+ * @param h Height of region in image original pixels
+ *
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_image_region_bring_in(Evas_Object *obj, int x, int y, int w, int h __UNUSED__)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int rx, ry, rw, rh;
+   if (!wd) return;
+   if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
+   rx = (x * wd->size.w) / wd->size.imw;
+   ry = (y * wd->size.h) / wd->size.imh;
+   rw = (w * wd->size.w) / wd->size.imw;
+   rh = (w * wd->size.h) / wd->size.imh;
+   if (rw < 1) rw = 1;
+   if (rh < 1) rh = 1;
+   if ((rx + rw) > wd->size.w) rx = wd->size.w - rw; 
+   if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
+   if (wd->zoom_animator)
+     {
+        wd->nosmooth--;
+        if (!wd->nosmooth) _smooth_update(obj);
+        ecore_animator_del(wd->zoom_animator);
+        wd->zoom_animator = NULL;
+        zoom_do(obj, 1.0);
+        evas_object_smart_callback_call(obj, "zoom,stop", NULL);
+    }
+   elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh);
+}
+
+/**
+ * Set the paused state for photocam
+ * 
+ * This sets the paused state to on (1) or off (0) for photocam. The default
+ * is on. This will stop zooming using animation ch change zoom levels and
+ * change instantly. This will stop any existing animations that are running.
+ * 
+ * @param obj The photocam object
+ * @param paused The pause state to set
+ *
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_paused_set(Evas_Object *obj, Eina_Bool paused)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->paused == !!paused) return;
+   wd->paused = paused;
+   if (wd->paused)
+     {
+        if (wd->zoom_animator)
+          {
+             ecore_animator_del(wd->zoom_animator);
+             wd->zoom_animator = NULL;
+             zoom_do(obj, 1.0);
+             evas_object_smart_callback_call(obj, "zoom,stop", NULL);
+          }
+     }
+}
+
+/**
+ * Get the paused state for photocam
+ * 
+ * This gets the current paused state for the photocam object.
+ * 
+ * @param obj The photocam object
+ * @return The current paused state
+ *
+ * @ingroup Photocam
+ */
+EAPI Eina_Bool
+elm_photocam_paused_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->paused;
+}
+
+/**
+ * Get the internal low-res image used for photocam
+ * 
+ * This gets the internal image object inside photocam. Do not modify it. It
+ * is for inspection only, and hooking callbacks to. Nothing else. It may be
+ * deleted at any time as well.
+ *
+ * @param obj The photocam object
+ * @return The internal image object handle, or NULL if none exists
+ *
+ * @ingroup Photocam
+ */
+EAPI Evas_Object *
+elm_photocam_internal_image_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->img;
+}
+
+/**
+ * Set the photocam scrolling bouncing.
+ *
+ * @param obj The photocam object
+ * @param h_bounce bouncing for horizontal
+ * @param v_bounce bouncing for vertical
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_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 photocam scrolling bouncing.
+ *
+ * @param obj The photocam object
+ * @param h_bounce bouncing for horizontal
+ * @param v_bounce bouncing for vertical
+ * @ingroup Photocam
+ */
+EAPI void
+elm_photocam_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_priv.h b/src/lib/elm_priv.h
new file mode 100644 (file)
index 0000000..90686c9
--- /dev/null
@@ -0,0 +1,204 @@
+#ifndef ELM_PRIV_H
+#define ELM_PRIV_H
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#ifdef HAVE_ELEMENTARY_X
+# include <Ecore_X.h>
+#endif
+#ifdef HAVE_ELEMENTARY_FB
+# include <Ecore_Fb.h>
+#endif
+#ifdef HAVE_ELEMENTARY_WINCE
+# include <Ecore_WinCE.h>
+#endif
+
+#include "els_pan.h"
+#include "els_scroller.h"
+#include "els_box.h"
+#include "els_icon.h"
+
+#include "elm_widget.h"
+
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_elm_log_dom, __VA_ARGS__)
+#define ERR(...)      EINA_LOG_DOM_ERR (_elm_log_dom, __VA_ARGS__)
+#define WRN(...)      EINA_LOG_DOM_WARN(_elm_log_dom, __VA_ARGS__)
+#define INF(...)      EINA_LOG_DOM_INFO(_elm_log_dom, __VA_ARGS__)
+#define DBG(...)      EINA_LOG_DOM_DBG (_elm_log_dom, __VA_ARGS__)
+
+typedef struct _Elm_Config    Elm_Config;
+typedef struct _Elm_Module    Elm_Module;
+
+struct _Elm_Theme
+{
+   Eina_List  *overlay;
+   Eina_List  *themes;
+   Eina_List  *extension;
+   Eina_Hash  *cache;
+   Elm_Theme  *ref_theme;
+   Eina_List  *referrers;
+   const char *theme;
+   int         ref;
+};
+
+/* increment this whenever we change config enough that you need new
+ * defaults for elm to work.
+ */
+#define ELM_CONFIG_EPOCH           0x0001
+/* increment this whenever a new set of config values are added but the users
+ * config doesn't need to be wiped - simply new values need to be put in
+ */
+#define ELM_CONFIG_FILE_GENERATION 0x0003
+#define ELM_CONFIG_VERSION         ((ELM_CONFIG_EPOCH << 16) | ELM_CONFIG_FILE_GENERATION)
+/* NB: profile configuration files (.src) must have their
+ * "config_version" entry's value up-to-date with ELM_CONFIG_VERSION
+ * (in decimal)!! */
+
+/* note: always remember to sync it with elm_config.c */
+extern const char *_elm_engines[];
+
+#define ELM_SOFTWARE_X11      (_elm_engines[0])
+#define ELM_SOFTWARE_FB       (_elm_engines[1])
+#define ELM_SOFTWARE_DIRECTFB (_elm_engines[2])
+#define ELM_SOFTWARE_16_X11   (_elm_engines[3])
+#define ELM_SOFTWARE_8_X11    (_elm_engines[4])
+#define ELM_XRENDER_X11       (_elm_engines[5])
+#define ELM_OPENGL_X11        (_elm_engines[6])
+#define ELM_SOFTWARE_WIN32    (_elm_engines[7])
+#define ELM_SOFTWARE_16_WINCE (_elm_engines[8])
+#define ELM_SOFTWARE_SDL      (_elm_engines[9])
+#define ELM_SOFTWARE_16_SDL   (_elm_engines[10])
+#define ELM_OPENGL_SDL        (_elm_engines[11])
+
+#define ELM_FONT_TOKEN_STYLE ":style="
+
+struct _Elm_Config
+{
+   int          config_version;
+   const char  *engine;
+   Eina_Bool    thumbscroll_enable;
+   int          thumbscroll_threshold;
+   double       thumbscroll_momentum_threshold;
+   double       thumbscroll_friction;
+   double       thumbscroll_bounce_friction;
+   double       page_scroll_friction;
+   double       bring_in_scroll_friction;
+   double       zoom_friction;
+   Eina_Bool    thumbscroll_bounce_enable;
+   double       thumbscroll_border_friction;
+   double       scale;
+   int          bgpixmap;
+   int          compositing;
+   Eina_List   *font_dirs;
+   Eina_List   *font_overlays;
+   int          font_hinting;
+   int          cache_flush_poll_interval;
+   Eina_Bool    cache_flush_enable;
+   int          image_cache;
+   int          font_cache;
+   int          edje_cache;
+   int          edje_collection_cache;
+   int          finger_size;
+   double       fps;
+   const char  *theme;
+   const char  *modules;
+   double       tooltip_delay;
+   Eina_Bool    cursor_engine_only;
+   Eina_Bool    focus_highlight_enable;
+   Eina_Bool    focus_highlight_animate;
+   int          toolbar_shrink_mode;
+   Eina_Bool    fileselector_expand_enable;
+   Eina_Bool    inwin_dialogs_enable;
+   int          icon_size;
+   double       longpress_timeout;
+};
+
+struct _Elm_Module
+{
+   int          version;
+   const char  *name;
+   const char  *as;
+   const char  *so_path;
+   const char  *data_dir;
+   const char  *bin_dir;
+   void        *handle;
+   void        *data;
+   void        *api;
+   int        (*init_func) (Elm_Module *m);
+   int        (*shutdown_func) (Elm_Module *m);
+   int          references;
+};
+
+void                _elm_win_shutdown(void);
+void                _elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme);
+
+Eina_Bool           _elm_theme_object_set(Evas_Object *parent, Evas_Object *o, const char *clas, const char *group, const char *style);
+Eina_Bool           _elm_theme_object_icon_set(Evas_Object *parent, Evas_Object *o, const char *group, const char *style);
+Eina_Bool           _elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style);
+Eina_Bool           _elm_theme_icon_set(Elm_Theme *th, Evas_Object *o, const char *group, const char *style);
+Eina_Bool           _elm_theme_parse(Elm_Theme *th, const char *theme);
+void                _elm_theme_shutdown(void);
+
+void                _elm_module_init(void);
+void                _elm_module_shutdown(void);
+void                _elm_module_parse(const char *s);
+Elm_Module         *_elm_module_find_as(const char *as);
+Elm_Module         *_elm_module_add(const char *name, const char *as);
+void                _elm_module_del(Elm_Module *m);
+const void         *_elm_module_symbol_get(Elm_Module *m, const char *name);
+
+void                _elm_widget_type_clear(void);
+void                _elm_widget_focus_region_show(const Evas_Object *obj);
+
+void               _elm_unneed_ethumb(void);
+
+void                _elm_rescale(void);
+
+void                _elm_config_init(void);
+void                _elm_config_sub_init(void);
+void                _elm_config_shutdown(void);
+Eina_Bool           _elm_config_save(void);
+void                _elm_config_reload(void);
+
+void                _elm_recache(void);
+
+const char         *_elm_config_current_profile_get(void);
+const char         *_elm_config_profile_dir_get(const char *prof, Eina_Bool is_user);
+Eina_List          *_elm_config_profiles_list(void);
+void                _elm_config_profile_set(const char *profile);
+
+void                _elm_config_engine_set(const char *engine);
+
+Eina_List          *_elm_config_font_overlays_list(void);
+void                _elm_config_font_overlay_set(const char *text_class, const char *font, Evas_Font_Size size);
+void                _elm_config_font_overlay_remove(const char *text_class);
+void                _elm_config_font_overlay_apply(void);
+Eina_List          *_elm_config_text_classes_get(void);
+void                _elm_config_text_classes_free(Eina_List *l);
+
+Elm_Font_Properties *_elm_font_properties_get(Eina_Hash **font_hash, const char *font);
+Eina_Hash           *_elm_font_available_hash_add(Eina_Hash *font_hash, const char *full_name);
+void                 _elm_font_available_hash_del(Eina_Hash *hash);
+
+void                 elm_tooltip_theme(Elm_Tooltip *tt);
+void                 elm_object_sub_tooltip_content_cb_set(Evas_Object *eventarea, Evas_Object *owner, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);
+void                 elm_cursor_theme(Elm_Cursor *cur);
+void                 elm_object_sub_cursor_set(Evas_Object *eventarea, Evas_Object *owner, const char *cursor);
+
+void                 elm_menu_clone(Evas_Object *from_menu, Evas_Object *to_menu, Elm_Menu_Item *parent);
+
+Eina_Bool           _elm_dangerous_call_check(const char *call);
+
+Evas_Object        *_elm_scroller_edje_object_get(Evas_Object *obj);
+
+char               *_elm_util_mkup_to_text(const char *mkup);
+char               *_elm_util_text_to_mkup(const char *text);
+
+extern char        *_elm_appname;
+extern Elm_Config  *_elm_config;
+extern const char  *_elm_data_dir;
+extern const char  *_elm_lib_dir;
+extern int          _elm_log_dom;
+extern Eina_List   *_elm_win_list;
+
+#endif
diff --git a/src/lib/elm_progressbar.c b/src/lib/elm_progressbar.c
new file mode 100644 (file)
index 0000000..b7e112f
--- /dev/null
@@ -0,0 +1,635 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Progressbar Progressbar
+ *
+ * The progressbar adds a widget for representing current progress
+ * of a job status
+ *
+ * A progressbar can be horizontal or vertical. It can contain an Icon and has a
+ * primary label as well as a units label (that is formatted with floating
+ * point values and thus accepts a printf-style format string, like
+ * “%1.2f units”.
+ *
+ *  Label, Icon and Unit strings/objects are optional.
+ *
+ * A progressbar may be inverted which means values invert, with high vales being
+ * on the left or top and low values on the right or bottom (as opposed to
+ * normally being low on the left or top and high on the bottom and right).
+ *
+ * The span of the progressbar is its length (horizontally or vertically).
+ * This will be scaled by the object or applications scaling factor. At any point
+ * code can query the progressbar for its value with elm_progressbar_value_get().
+ */
+
+#define MIN_RATIO_LVL 0.0
+#define MAX_RATIO_LVL 1.0
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *progressbar;
+   Evas_Object *spacer;
+   Evas_Object *icon;
+   Evas_Coord size;
+   Eina_Bool horizontal : 1;
+   Eina_Bool inverted : 1;
+   Eina_Bool pulse : 1;
+   Eina_Bool pulse_state : 1;
+   const char *units;
+   const char *label;
+   double val;
+};
+
+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 _units_set(Evas_Object *obj);
+static void _val_set(Evas_Object *obj);
+
+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);
+   if (wd->units) eina_stringshare_del(wd->units);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->horizontal)
+     _elm_theme_object_set(obj, wd->progressbar, "progressbar", "horizontal", elm_widget_style_get(obj));
+   else
+     _elm_theme_object_set(obj, wd->progressbar, "progressbar", "vertical", elm_widget_style_get(obj));
+   
+   if (wd->icon)
+     {
+       edje_object_part_swallow(wd->progressbar, "elm.swallow.content", wd->icon);
+       edje_object_signal_emit(wd->progressbar, "elm,state,icon,visible", "elm");
+     }
+   if (wd->label)
+     {
+        edje_object_part_text_set(wd->progressbar, "elm.text", wd->label);
+        edje_object_signal_emit(wd->progressbar, "elm,state,text,visible", "elm");
+     }
+   if (wd->pulse)
+      edje_object_signal_emit(wd->progressbar, "elm,state,pulse", "elm");
+   else
+      edje_object_signal_emit(wd->progressbar, "elm,state,fraction", "elm");
+   if (wd->pulse_state)
+      edje_object_signal_emit(wd->progressbar, "elm,state,pulse,start", "elm");
+   
+   if ((wd->units) && (!wd->pulse))
+      edje_object_signal_emit(wd->progressbar, "elm,state,units,visible", "elm");
+   
+   if (wd->horizontal)
+     evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
+   else
+     evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
+
+   edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
+
+   if (wd->inverted)
+      edje_object_signal_emit(wd->progressbar, "elm,state,inverted,on", "elm");
+   
+   _units_set(obj);
+   edje_object_message_signal_process(wd->progressbar);
+   edje_object_scale_set(wd->progressbar, elm_widget_scale_get(obj) * _elm_config->scale);
+   _val_set(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;
+   if (!wd) return;
+   edje_object_size_min_restricted_calc(wd->progressbar, &minw, &minh, minw, minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (obj != wd->icon) 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;
+   if (sub == wd->icon)
+     {
+       edje_object_signal_emit(wd->progressbar, "elm,state,icon,hidden", "elm");
+       evas_object_event_callback_del_full
+         (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+       wd->icon = NULL;
+       edje_object_message_signal_process(wd->progressbar);
+       _sizing_eval(obj);
+     }
+}
+
+static void
+_val_set(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double pos;
+   if (!wd) return;
+   pos = wd->val;
+   if (wd->inverted) pos = MAX_RATIO_LVL - pos;
+   edje_object_part_drag_value_set(wd->progressbar, "elm.cur.progressbar", pos, pos);
+}
+
+static void
+_units_set(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->units)
+     {
+        char buf[1024];
+        snprintf(buf, sizeof(buf), wd->units, 100 * wd->val);
+        edje_object_part_text_set(wd->progressbar, "elm.text.status", buf);
+     }
+   else
+     edje_object_part_text_set(wd->progressbar, "elm.text.status", NULL);
+}
+
+/**
+ * Add a new progressbar to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Progressbar
+ */
+EAPI Evas_Object *
+elm_progressbar_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "progressbar");
+   elm_widget_type_set(obj, "progressbar");
+   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, EINA_FALSE);
+
+   wd->horizontal = EINA_TRUE;
+   wd->inverted = EINA_FALSE;
+   wd->pulse = EINA_FALSE;
+   wd->pulse_state = EINA_FALSE;
+   wd->units = eina_stringshare_add("%.0f %%");
+   wd->val = MIN_RATIO_LVL;
+
+   wd->progressbar = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->progressbar, "progressbar", "horizontal", "default");
+   elm_widget_resize_object_set(obj, wd->progressbar);
+
+   wd->spacer = evas_object_rectangle_add(e);
+   evas_object_color_set(wd->spacer, 0, 0, 0, 0);
+   evas_object_pass_events_set(wd->spacer, EINA_TRUE);
+   elm_widget_sub_object_add(obj, wd->spacer);
+   edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   _units_set(obj);
+   _val_set(obj);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Normally the progressbar will display and interpret values from low to high.
+ * This display a progressbar for jobs with unknow state of progression,
+ * (the cursor pulse right to left and left to right, and loop) if pulse is set to 1.
+ *
+ * @param obj The progressbar object
+ * @param pulse The pulse flag. 1 == pulse, 0 == normal
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_pulse_set(Evas_Object *obj, Eina_Bool pulse)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   pulse = !!pulse;
+   if (wd->pulse == pulse) return;
+   wd->pulse = pulse;
+   _theme_hook(obj);
+}
+
+/**
+ * Normally the progressbar will display and interpret values from low to high.
+ * This display a progressbar for jobs with unknow state of progression,
+ * (the cursor pulse right to left and left to right, and loop) if pulse is set to 1.
+ *
+ * @param obj The progressbar object
+ * @return The pulse flag
+ * (1 == pulse, 0 == normal)
+ *
+ * @ingroup Progressbar
+ */
+EAPI Eina_Bool
+elm_progressbar_pulse_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->pulse;
+}
+
+/**
+ * Stat/Stop de pulse action
+ *
+ * @param obj The progressbar object
+ * @param state The pulse flag. 1 == start pulse, 0 == stop pulse
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_pulse(Evas_Object *obj, Eina_Bool state)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   state = !!state;
+   if ((!wd->pulse) && (wd->pulse_state == state)) return;
+   wd->pulse_state = state;
+   if (wd->pulse_state)
+     edje_object_signal_emit(wd->progressbar, "elm,state,pulse,start", "elm");
+   else
+     edje_object_signal_emit(wd->progressbar, "elm,state,pulse,stop", "elm");
+}
+
+/**
+ * Set the value the progressbar indicates
+ *
+ * @param obj The progressbar object
+ * @param val The fraction value (must be between 0.0 and 1.0)
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_value_set(Evas_Object *obj, double val)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->val == val) return;
+   wd->val = val;
+   if (wd->val < MIN_RATIO_LVL) wd->val = MIN_RATIO_LVL;
+   if (wd->val > MAX_RATIO_LVL) wd->val = MAX_RATIO_LVL;
+   _val_set(obj);
+   _units_set(obj);
+}
+
+
+/**
+ * Get the value the progressbar has
+ *
+ * @param obj The progressbar object
+ * @return The value of the progressbar
+ *
+ * @ingroup Progressbar
+ */
+EAPI double
+elm_progressbar_value_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->val;
+}
+
+/**
+ * Set the label of the progressbar
+ *
+ * @param obj The progressbar object
+ * @param label The text label string in UTF-8
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_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);
+   if (label)
+     {
+       edje_object_signal_emit(wd->progressbar, "elm,state,text,visible", "elm");
+       edje_object_message_signal_process(wd->progressbar);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->progressbar, "elm,state,text,hidden", "elm");
+       edje_object_message_signal_process(wd->progressbar);
+     }
+   edje_object_part_text_set(wd->progressbar, "elm.text", label);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the label of the progressbar
+ *
+ * @param obj The progressbar object
+ * @return The text label string in UTF-8
+ *
+ * @ingroup Progressbar
+ */
+EAPI const char *
+elm_progressbar_label_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->label;
+}
+
+/**
+ * Set the icon object of the progressbar object
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_progressbar_icon_unset() function.
+ *
+ * @param obj The progressbar object
+ * @param icon The icon object
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_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);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->progressbar, "elm.swallow.content", icon);
+       edje_object_signal_emit(wd->progressbar, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->progressbar);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the icon object of the progressbar object
+ *
+ * @param obj The progressbar object
+ * @return The icon object
+ *
+ * @ingroup Progressbar
+ */
+EAPI Evas_Object *
+elm_progressbar_icon_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->icon;
+}
+
+/**
+ * Unset the icon used for the progressbar object
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The progressbar object
+ * @return The icon object that was being used
+ *
+ * @ingroup Progressbar
+ */
+EAPI Evas_Object *
+elm_progressbar_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->icon) return NULL;
+   Evas_Object *icon = wd->icon;
+   elm_widget_sub_object_del(obj, wd->icon);
+   edje_object_part_unswallow(wd->progressbar, wd->icon);
+   wd->icon = NULL;
+   return icon;
+}
+
+/**
+ * Set the length of the progression region of the progressbar
+ *
+ * This sets the minimum width or height (depending on orientation) of the
+ * area of the progressbar that allows the progressbar to be dragged around. This in
+ * turn affects the objects minimum size (along with icon label and unit
+ * text).
+ *
+ * @param obj The progressbar object
+ * @param size The length of the progressbar area
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_span_size_set(Evas_Object *obj, Evas_Coord size)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->size == size) return;
+   wd->size = size;
+   if (wd->horizontal)
+     evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
+   else
+     evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
+   edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the length of the progression region of the progressbar
+ *
+ * @param obj The progressbar object
+ * @return The length of the progressbar area
+ *
+ * @ingroup Progressbar
+ */
+EAPI Evas_Coord
+elm_progressbar_span_size_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->size;
+}
+
+/**
+ * Set the format string of the unit area
+ *
+ * If NULL, this disabls the unit area display. If not it sets the format
+ * string for the unit text. The unit text is provided a floating point
+ * value, so the unit text can display up to 1 floating point falue. Note that
+ * this is optional. Use a format string such as "%1.2f meters" for example.
+ *
+ * @param obj The progressbar object
+ * @param units The format string for the units display
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_unit_format_set(Evas_Object *obj, const char *units)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->units, units);
+   if (units)
+     {
+       edje_object_signal_emit(wd->progressbar, "elm,state,units,visible", "elm");
+       edje_object_message_signal_process(wd->progressbar);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->progressbar, "elm,state,units,hidden", "elm");
+       edje_object_message_signal_process(wd->progressbar);
+     }
+   _units_set(obj);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the format string of the unit area
+ *
+ * @param obj The progressbar object
+ * @return The format string for the units display
+ *
+ * @ingroup Progressbar
+ */
+EAPI const char *
+elm_progressbar_unit_format_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->units;
+}
+
+/**
+ * Set orientation of the progressbar
+ *
+ * @param obj The progressbar object
+ * @param horizontal If set, the progressbar will be horizontal
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   horizontal = !!horizontal;
+   if (wd->horizontal == horizontal) return;
+   wd->horizontal = horizontal;
+   _theme_hook(obj);
+}
+
+/**
+ * Gets orientation of the progressbar
+ *
+ * @param obj The progressbar object
+ * @return The orientation
+ * (0 = vertical, 1 = horizontal)
+ *
+ * @ingroup Progressbar
+ */
+EAPI Eina_Bool
+elm_progressbar_horizontal_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->horizontal;
+}
+
+/**
+ * Invert the progressbar display
+ *
+ * Normally the progressbar will display and interpret values from low to high
+ * and when horizontal that is left to right. When vertical that is top
+ * to bottom. This inverts this (so from right to left or bottom to top) if
+ * inverted is set to 1.
+ *
+ * @param obj The progressbar object
+ * @param inverted The inverted flag. 1 == inverted, 0 == normal
+ *
+ * @ingroup Progressbar
+ */
+EAPI void
+elm_progressbar_inverted_set(Evas_Object *obj, Eina_Bool inverted)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   inverted = !!inverted;
+   if (wd->inverted == inverted) return;
+   wd->inverted = inverted;
+   if (wd->inverted)
+     edje_object_signal_emit(wd->progressbar, "elm,state,inverted,on", "elm");
+   else
+     edje_object_signal_emit(wd->progressbar, "elm,state,inverted,off", "elm");
+   edje_object_message_signal_process(wd->progressbar);
+   _val_set(obj);
+   _units_set(obj);
+}
+
+/**
+ * Gets if the progressbar will displayed inverted
+ *
+ * @param obj The progressbar object
+ * @return The inverted flag
+ * (1 == inverted, 0 == normal)
+ *
+ * @ingroup Progressbar
+ */
+EAPI Eina_Bool
+elm_progressbar_inverted_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->inverted;
+}
diff --git a/src/lib/elm_radio.c b/src/lib/elm_radio.c
new file mode 100644 (file)
index 0000000..c01572f
--- /dev/null
@@ -0,0 +1,587 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Radio Radio
+ *
+ * The radio button allows for 1 or more selectors to be created to select 1
+ * of a set of options.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * changed - This is called whenever the user changes the state of one of the
+ * radio objects within the group of radio objects that work together.
+ *
+ * A radio object contains an indicator, an optional Label and an optional
+ * icon object. They work normally in groups of 2 or more. When you create a
+ * radio (if it is not the first member of the group), simply add it to the
+ * group by adding it to any other member of the group that already exists
+ * (or the first member) with elm_radio_group_add() with the second parameter
+ * being the existing group member. The radio object(s) will select from one
+ * of a set of integer values, so any value they are configuring needs to be
+ * mapped to a set of integers. To configure what value that radio object
+ * represents, use  elm_radio_state_value_set() to set the integer it
+ * represents. To set the value the whole group is to indicate use
+ * elm_radio_value_set() on any group member, and to get the groups value use
+ * elm_radio_value_get(). For convenience the radio objects are also able to
+ * directly set an integer (int) to the value that is selected. To specify
+ * the pointer to this integer to modify, use elm_radio_value_pointer_set().
+ * The radio objects will modify this directly. That implies the pointer must
+ * point to valid memory for as long as the radio objects exist.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Group Group;
+
+struct _Group
+{
+   int value;
+   int *valuep;
+   Eina_List *radios;
+};
+
+struct _Widget_Data
+{
+   Evas_Object *radio;
+   Evas_Object *icon;
+   int value;
+   const char *label;
+   Eina_Bool state;
+   Group *group;
+};
+
+static const char *widtype = NULL;
+static void _state_set(Evas_Object *obj, Eina_Bool state);
+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 _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 _signal_radio_on(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _activate(Evas_Object *obj);
+static void _activate_hook(Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+
+static const char SIG_CHANGED[] = "changed";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CHANGED, ""},
+  {NULL, NULL}
+};
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   if ((strcmp(ev->keyname, "Return")) &&
+       (strcmp(ev->keyname, "KP_Enter")) &&
+       (strcmp(ev->keyname, "space")))
+     return EINA_FALSE;
+   _activate(obj);
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+}
+
+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);
+   wd->group->radios = eina_list_remove(wd->group->radios, obj);
+   if (!wd->group->radios) free(wd->group);
+   wd->group = NULL;
+   free(wd);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->radio, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->radio, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->radio, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->radio, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->radio, "radio", "base", elm_widget_style_get(obj));
+   if (wd->icon)
+     edje_object_signal_emit(wd->radio, "elm,state,icon,visible", "elm");
+   else
+     edje_object_signal_emit(wd->radio, "elm,state,icon,hidden", "elm");
+   if (wd->state)
+     edje_object_signal_emit(wd->radio, "elm,state,radio,on", "elm");
+   else
+     edje_object_signal_emit(wd->radio, "elm,state,radio,off", "elm");
+   if (wd->label)
+     edje_object_signal_emit(wd->radio, "elm,state,text,visible", "elm");
+   else
+     edje_object_signal_emit(wd->radio, "elm,state,text,hidden", "elm");
+   edje_object_part_text_set(wd->radio, "elm.text", wd->label);
+   if (elm_widget_disabled_get(obj))
+     {
+        edje_object_signal_emit(wd->radio, "elm,state,disabled", "elm");
+        if (wd->state) _state_set(obj, 0);
+     }
+   edje_object_message_signal_process(wd->radio);
+   edje_object_scale_set(wd->radio, 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) return;
+   if (elm_widget_disabled_get(obj))
+     {
+        edje_object_signal_emit(wd->radio, "elm,state,disabled", "elm");
+        if (wd->state) _state_set(obj, 0);
+     }
+   else
+     edje_object_signal_emit(wd->radio, "elm,state,enabled", "elm");
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->radio, &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, -1, -1);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (obj != wd->icon) 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;
+   if (sub == wd->icon)
+     {
+       edje_object_signal_emit(wd->radio, "elm,state,icon,hidden", "elm");
+       evas_object_event_callback_del_full
+         (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+       wd->icon = NULL;
+       _sizing_eval(obj);
+     }
+}
+
+static void
+_state_set(Evas_Object *obj, Eina_Bool state)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((state != wd->state) && (!elm_widget_disabled_get(obj)))
+     {
+       wd->state = state;
+       if (wd->state)
+         edje_object_signal_emit(wd->radio, "elm,state,radio,on", "elm");
+       else
+         edje_object_signal_emit(wd->radio, "elm,state,radio,off", "elm");
+     }
+}
+
+static void
+_state_set_all(Widget_Data *wd)
+{
+   const Eina_List *l;
+   Evas_Object *child, *selected = NULL;
+   Eina_Bool disabled = EINA_FALSE;
+   EINA_LIST_FOREACH(wd->group->radios, l, child)
+     {
+       Widget_Data *wd2 = elm_widget_data_get(child);
+        if (wd2->state) selected = child;
+       if (wd2->value == wd->group->value)
+          {
+             _state_set(child, 1);
+             if (!wd2->state) disabled = EINA_TRUE;
+          }
+       else _state_set(child, 0);
+     }
+   if ((disabled) && (selected)) _state_set(selected, 1);
+}
+
+static void
+_activate(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->group->value == wd->value) return;
+   wd->group->value = wd->value;
+   if (wd->group->valuep) *(wd->group->valuep) = wd->group->value;
+   _state_set_all(wd);
+   evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
+}
+
+static void
+_activate_hook(Evas_Object *obj)
+{
+   _activate(obj);
+}
+
+static void
+_signal_radio_on(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _activate(data);
+}
+
+/**
+  * Add a new radio to the parent
+  *
+  * @param parent The parent object
+  * @return The new object or NULL if it cannot be created
+  *
+  * @ingroup Radio
+  */
+EAPI Evas_Object *
+elm_radio_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "radio");
+   elm_widget_type_set(obj, "radio");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_activate_hook_set(obj, _activate_hook);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->radio = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->radio, "radio", "base", "default");
+   edje_object_signal_callback_add(wd->radio, "elm,action,radio,on", "", _signal_radio_on, obj);
+   edje_object_signal_callback_add(wd->radio, "elm,action,radio,toggle", "", _signal_radio_on, obj);
+   elm_widget_resize_object_set(obj, wd->radio);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   wd->group = calloc(1, sizeof(Group));
+   wd->group->radios = eina_list_append(wd->group->radios, obj);
+   wd->state = 0;
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the text label of the radio object
+ *
+ * @param obj The radio object
+ * @param label The text label string in UTF-8
+ *
+ * @ingroup Radio
+ */
+EAPI void
+elm_radio_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);
+   if (label)
+     {
+       edje_object_signal_emit(wd->radio, "elm,state,text,visible", "elm");
+       edje_object_message_signal_process(wd->radio);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->radio, "elm,state,text,hidden", "elm");
+       edje_object_message_signal_process(wd->radio);
+     }
+   edje_object_part_text_set(wd->radio, "elm.text", label);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the text label of the radio object
+ *
+ * @param obj The radio object
+ * @return The text label string in UTF-8
+ *
+ * @ingroup Radio
+ */
+EAPI const char *
+elm_radio_label_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->label;
+}
+
+/**
+ * Set the icon object of the radio object
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_radio_icon_unset() function.
+ *
+ * @param obj The radio object
+ * @param icon The icon object
+ *
+ * @ingroup Radio
+ */
+EAPI void
+elm_radio_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);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->radio, "elm.swallow.content", icon);
+       edje_object_signal_emit(wd->radio, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->radio);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the icon object of the radio object
+ *
+ * @param obj The radio object
+ * @return The icon object
+ *
+ * @ingroup Radio
+ */
+EAPI Evas_Object *
+elm_radio_icon_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->icon;
+}
+
+/**
+ * Unset the icon used for the radio object
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The radio object
+ * @return The icon object that was being used
+ *
+ * @ingroup Radio
+ */
+EAPI Evas_Object *
+elm_radio_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->icon) return NULL;
+   Evas_Object *icon = wd->icon;
+   elm_widget_sub_object_del(obj, wd->icon);
+   edje_object_part_unswallow(wd->radio, wd->icon);
+   wd->icon = NULL;
+   return icon;
+}
+
+/**
+ * Add this radio to a group of other radio objects
+ *
+ * Radio objects work in groups. Each member should have a different integer
+ * value assigned. In order ro have them work as a group, they need to know
+ * about eacthother. This adds the given radio object to the group of which
+ * the group object indicated is a member.
+ *
+ * @param obj The radio object
+ * @param group The object whose group the object is to join
+ *
+ * @ingroup Radio
+ */
+EAPI void
+elm_radio_group_add(Evas_Object *obj, Evas_Object *group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Widget_Data *wd2 = elm_widget_data_get(group);
+   if (!wd) return;
+   if (!wd2)
+     {
+       if (eina_list_count(wd->group->radios) == 1)
+         return;
+       wd->group->radios = eina_list_remove(wd->group->radios, obj);
+       wd->group = calloc(1, sizeof(Group));
+       wd->group->radios = eina_list_append(wd->group->radios, obj);
+     }
+   else if (wd->group == wd2->group) return;
+   else
+     {
+       wd->group->radios = eina_list_remove(wd->group->radios, obj);
+       if (!wd->group->radios) free(wd->group);
+       wd->group = wd2->group;
+       wd->group->radios = eina_list_append(wd->group->radios, obj);
+     }
+   if (wd->value == wd->group->value) _state_set(obj, 1);
+   else _state_set(obj, 0);
+}
+
+/**
+ * Set the integer value that this radio object represents
+ *
+ * This sets the value of the radio.
+ *
+ * @param obj The radio object
+ * @param value The value to use if this radio object is selected
+ *
+ * @ingroup Radio
+ */
+EAPI void
+elm_radio_state_value_set(Evas_Object *obj, int value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->value = value;
+   if (wd->value == wd->group->value) _state_set(obj, 1);
+   else _state_set(obj, 0);
+}
+
+/**
+ * Get the integer value that this radio object represents
+ *
+ * This gets the value of the radio.
+ *
+ * @param obj The radio object
+ * @return The value used if this radio object is selected
+ *
+ * @ingroup Radio
+ */
+EAPI int
+elm_radio_state_value_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->value;
+}
+
+/**
+ * Set the value of the radio.
+ *
+ * This sets the value of the radio group and will also set the value if
+ * pointed to, to the value supplied, but will not call any callbacks.
+ *
+ * @param obj The radio object
+ * @param value The value to use for the group
+ *
+ * @ingroup Radio
+ */
+EAPI void
+elm_radio_value_set(Evas_Object *obj, int value)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (value == wd->group->value) return;
+   wd->group->value = value;
+   if (wd->group->valuep) *(wd->group->valuep) = wd->group->value;
+   _state_set_all(wd);
+}
+
+/**
+ * Get the state of the radio object
+ *
+ * @param obj The radio object
+ * @return The integer state
+ *
+ * @ingroup Radio
+ */
+EAPI int
+elm_radio_value_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->group->value;
+}
+
+/**
+ * Set a convenience pointer to a integer to change
+ *
+ * This sets a pointer to a integer, that, in addition to the radio objects
+ * state will also be modified directly. To stop setting the object pointed
+ * to simply use NULL as the valuep parameter. If valuep is not NULL, then
+ * when this is called, the radio objects state will also be modified to
+ * reflect the value of the integer valuep points to, just like calling
+ * elm_radio_value_set().
+ *
+ * @param obj The radio object
+ * @param valuep Pointer to the integer to modify
+ *
+ * @ingroup Radio
+ */
+EAPI void
+elm_radio_value_pointer_set(Evas_Object *obj, int *valuep)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (valuep)
+     {
+       wd->group->valuep = valuep;
+       if (*(wd->group->valuep) != wd->group->value)
+         {
+            wd->group->value = *(wd->group->valuep);
+            _state_set_all(wd);
+         }
+     }
+   else
+     {
+       wd->group->valuep = NULL;
+     }
+}
diff --git a/src/lib/elm_scroller.c b/src/lib/elm_scroller.c
new file mode 100644 (file)
index 0000000..1bd94a0
--- /dev/null
@@ -0,0 +1,919 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Scroller Scroller
+ *
+ * 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 const char *widtype = NULL;
+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 _on_focus_hook(void *data, Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+
+
+static const char SIG_SCROLL[] = "scroll";
+static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
+static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
+static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
+static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
+static const char SIG_EDGE_LEFT[] = "edge,left";
+static const char SIG_EDGE_RIGHT[] = "edge,right";
+static const char SIG_EDGE_TOP[] = "edge,top";
+static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_SCROLL, ""},
+  {SIG_SCROLL_ANIM_START, ""},
+  {SIG_SCROLL_ANIM_STOP, ""},
+  {SIG_SCROLL_DRAG_START, ""},
+  {SIG_SCROLL_DRAG_STOP, ""},
+  {SIG_EDGE_LEFT, ""},
+  {SIG_EDGE_RIGHT, ""},
+  {SIG_EDGE_TOP, ""},
+  {SIG_EDGE_BOTTOM, ""},
+  {NULL, NULL}
+};
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   Evas_Coord x = 0;
+   Evas_Coord y = 0;
+   Evas_Coord step_x = 0;
+   Evas_Coord step_y = 0;
+   Evas_Coord max_x = 0;
+   Evas_Coord max_y = 0;
+   Evas_Coord v_w = 0;
+   Evas_Coord v_h = 0;
+   Evas_Coord page_x = 0;
+   Evas_Coord page_y = 0;
+
+   elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
+   elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
+   elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
+   elm_scroller_child_size_get(obj, &max_x, &max_y);
+
+   if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
+     {
+        x -= step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
+     {
+        x += step_x;
+     }
+   else if ((!strcmp(ev->keyname, "Up"))  || (!strcmp(ev->keyname, "KP_Up")))
+     {
+        y -= step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
+     {
+        y += step_y;
+     }
+   else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
+     {
+        y = 0;
+     }
+   else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
+     {
+        y = max_y - v_h;
+     }
+   else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
+     {
+       if (page_y < 0)
+         y -= -(page_y * v_h) / 100;
+       else
+           y -= page_y;
+     }
+   else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
+     {
+       if (page_y < 0)
+         y += -(page_y * v_h) / 100;
+       else
+         y += page_y;
+     }
+   else return EINA_FALSE;
+
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   elm_smart_scroller_child_pos_set(wd->scr, x, y);
+   return EINA_TRUE;
+}
+
+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))
+     {
+        edje_object_signal_emit(wd->scr, "elm,action,focus", "elm");
+        evas_object_focus_set(wd->scr, EINA_TRUE);
+     }
+   else
+     {
+        edje_object_signal_emit(wd->scr, "elm,action,unfocus", "elm");
+        evas_object_focus_set(wd->scr, EINA_FALSE);
+     }
+}
+
+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)
+     {
+        Evas_Object *edj;
+        const char *str;
+
+        elm_smart_scroller_object_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);
+        edj = elm_smart_scroller_edje_object_get(wd->scr);
+        str = edje_object_data_get(edj, "focus_highlight");
+        if ((str) && (!strcmp(str, "on")))
+          elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
+        else
+          elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
+     }
+   _sizing_eval(obj);
+}
+
+static Eina_Bool
+_elm_scroller_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *cur;
+
+   if ((!wd) || (!wd->content))
+     return EINA_FALSE;
+
+   cur = wd->content;
+
+   /* Try Focus cycle in subitem */
+   if ((elm_widget_can_focus_get(cur)) || (elm_widget_child_can_focus_get(cur)))
+      return elm_widget_focus_next_get(cur, dir, next);
+
+   /* Return */
+   *next = (Evas_Object *)obj;
+   return !elm_widget_focus_get(obj);
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
+        emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
+        emission, source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(
+        elm_smart_scroller_edje_object_get(wd->scr), emission, source,
+        func_cb, data);
+}
+
+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);
+   if (wd->scr)
+     elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
+}
+
+static void
+_focus_region_hook(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->scr)
+     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, yw;
+
+   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, &yw);
+   if (wd->scr)
+     {
+        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 (yw > 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(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_max_get(obj, &maxw, &maxh);
+        if ((maxw > 0) && (w > maxw)) w = maxw;
+        if ((maxh > 0) && (h > maxh)) h = maxh;
+        evas_object_size_hint_min_set(obj, w, h);
+     }
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _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;
+   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);
+     }
+   else if (sub == wd->scr)
+     wd->scr = NULL;
+}
+
+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;
+   if (wd->scr)
+     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;
+   if (wd->scr)
+     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;
+   if (wd->scr)
+     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;
+   if (wd->scr)
+     elm_smart_scroller_freeze_set(wd->scr, 0);
+}
+
+static void
+_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_edge_left(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_EDGE_LEFT, NULL);
+}
+
+static void
+_edge_right(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_EDGE_RIGHT, NULL);
+}
+
+static void
+_edge_top(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_EDGE_TOP, NULL);
+}
+
+static void
+_edge_bottom(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_EDGE_BOTTOM, NULL);
+}
+
+static void
+_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
+}
+
+static void
+_scroll_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
+}
+
+static void
+_scroll_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
+}
+
+static void
+_scroll_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
+}
+
+static void
+_scroll_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, SIG_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 *
+elm_scroller_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord minw, minh;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "scroller");
+   elm_widget_type_set(obj, "scroller");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_widget_focus_next_hook_set(obj, _elm_scroller_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_hook);
+   elm_widget_focus_region_hook_set(obj, _focus_region_hook);
+
+   wd->widget_name = eina_stringshare_add("scroller");
+   wd->widget_base = eina_stringshare_add("base");
+   
+   wd->scr = elm_smart_scroller_add(e);
+   elm_smart_scroller_widget_set(wd->scr, obj);
+   _theme_hook(obj);
+   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(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);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+Evas_Object *
+_elm_scroller_edje_object_get(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return elm_smart_scroller_edje_object_get(wd->scr);
+}
+
+/**
+ * Set the content of the scroller widget (the object to be scrolled around).
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_scroller_content_unset() function.
+ *
+ * @param obj The scroller object
+ * @param content The new content object
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+elm_scroller_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content) evas_object_del(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);
+        if (wd->scr)
+          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);
+}
+
+/**
+ * Get the content of the scroller widget
+ *
+ * Return the content object which is set for this widget
+ *
+ * @param obj The slider object
+ * @return The content that is being used
+ *
+ * @ingroup Scroller
+ */
+EAPI Evas_Object *
+elm_scroller_content_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->content;
+}
+
+/**
+ * Unset the content of the scroller widget
+ *
+ * Unparent and return the content object which was set for this widget
+ *
+ * @param obj The slider object
+ * @return The content that was being used
+ *
+ * @ingroup Scroller
+ */
+EAPI Evas_Object *
+elm_scroller_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *content;
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   content = wd->content;
+   elm_widget_sub_object_del(obj, wd->content);
+   edje_object_part_unswallow(wd->scr, wd->content);
+   wd->content = NULL;
+   return content;
+}
+
+/**
+ * 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")
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+elm_scroller_custom_widget_base_theme_set(Evas_Object *obj, const char *widget, const char *base)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(widget);
+   EINA_SAFETY_ON_NULL_RETURN(base);
+   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
+elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   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
+elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->scr)) return;
+   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
+elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   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) || (!wd->scr)) return;
+   if ((policy_h >= 3) || (policy_v >= 3)) return;
+   elm_smart_scroller_policy_set(wd->scr, map[policy_h], map[policy_v]);
+}
+
+EAPI void
+elm_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->scr)) return;
+   elm_smart_scroller_policy_get(wd->scr,
+                                 (Elm_Smart_Scroller_Policy *) policy_h,
+                                 (Elm_Smart_Scroller_Policy *) 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
+elm_scroller_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->scr)) return;
+   if ((x) || (y)) elm_smart_scroller_child_pos_get(wd->scr, x, y);
+   if ((w) || (h)) 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
+elm_scroller_child_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;
+   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 parameters for each axis.
+ *
+ * @param obj The scroller object
+ * @param h_bounce Will the scroller bounce horizontally or not
+ * @param v_bounce Will the scroller bounce vertically or not
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+elm_scroller_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) || (!wd->scr)) return;
+   elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
+}
+
+/**
+ * Get the bounce mode
+ *
+ * @param obj The Scroller object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+elm_scroller_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);
+}
+
+/**
+ * Set scroll page size relative to viewport size.
+ *
+ * The scroller is capable 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 content 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
+elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->pagerel_h = h_pagerel;
+   wd->pagerel_v = v_pagerel;
+   if (wd->scr)
+     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 relative 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
+elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->pagesize_h = h_pagesize;
+   wd->pagesize_v = v_pagesize;
+   if (wd->scr)
+     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
+elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!wd->scr)) return;
+   elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
+}
+
+
+/**
+ * Set event propagation on a scroller
+ *
+ * This enables or disabled event propagation from the scroller content to
+ * the scroller and its parent. By default event propagation is disabled.
+ * 
+ * @param obj The scroller object
+ * @param propagation If propagation is enabled or not
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   evas_object_propagate_events_set(wd->scr, propagation);
+}
+
+/**
+ * Get event propagation for a scroller
+ *
+ * This gets the event propagation for a scroller. See 
+ * elm_scroller_propagate_events_set() for more information
+ * 
+ * @param obj The scroller object
+ * @return The propagation state
+ *
+ * @ingroup Scroller
+ */
+EAPI Eina_Bool
+elm_scroller_propagate_events_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 evas_object_propagate_events_get(wd->scr);
+}
diff --git a/src/lib/elm_separator.c b/src/lib/elm_separator.c
new file mode 100644 (file)
index 0000000..6580bd3
--- /dev/null
@@ -0,0 +1,130 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Separator Separator
+ *
+ * A separator is a widget that adds a very thin object to separate other objects.
+ * A separator can be vertical or horizontal.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *sep;
+   Eina_Bool horizontal;
+};
+
+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
+_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->horizontal)
+     _elm_theme_object_set(obj, wd->sep, "separator", "horizontal", elm_widget_style_get(obj));
+   else
+     _elm_theme_object_set(obj, wd->sep, "separator", "vertical", elm_widget_style_get(obj));
+   edje_object_scale_set(wd->sep, 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->sep, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+   evas_object_size_hint_align_set(obj, maxw, maxh);
+}
+
+/**
+ * Add a separator object to @p parent
+ *
+ * @param parent The parent object
+ *
+ * @return The separator object, or NULL upon failure
+ *
+ * @ingroup Separator
+ */
+EAPI Evas_Object *
+elm_separator_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "separator");
+   wd->horizontal = EINA_FALSE;
+   elm_widget_type_set(obj, "separator");
+   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, EINA_FALSE);
+
+   wd->sep = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->sep, "separator", "vertical", "default");
+   elm_widget_resize_object_set(obj, wd->sep);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the horizontal mode of a separator object
+ *
+ * @param obj The separator object
+ * @param horizontal If true, the separator is horizontal
+ *
+ * @ingroup Separator
+ */
+EAPI void
+elm_separator_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   horizontal = !!horizontal;
+   if (wd->horizontal == horizontal) return;
+   wd->horizontal = horizontal;
+   _theme_hook(obj);
+}
+
+/**
+ * Get the horizontal mode of a separator object
+ *
+ * @param obj The separator object
+ * @return If true, the separator is horizontal
+ *
+ * @ingroup Separator
+ */
+EAPI Eina_Bool
+elm_separator_horizontal_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->horizontal;
+}
diff --git a/src/lib/elm_slider.c b/src/lib/elm_slider.c
new file mode 100644 (file)
index 0000000..681298b
--- /dev/null
@@ -0,0 +1,1142 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Slider Slider
+ *
+ * The slider adds a dragable “slider” widget for selecting the value of
+ * something within a range.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * changed - Whenever the slider value is changed by the user.
+ *
+ * delay,changed - A short time after the value is changed by the user.
+ * This will be called only when the user stops dragging for a very short
+ * period or when they release their finger/mouse, so it avoids possibly
+ * expensive reactions to the value change.
+ *
+ * slider,drag,start - dragging the slider indicator around has started
+ *
+ * slider,drag,stop - dragging the slider indicator around has stopped
+ *
+ * A slider can be horizontal or vertical. It can contain an Icon and has a
+ * primary label as well as a units label (that is formatted with floating
+ * point values and thus accepts a printf-style format string, like
+ * “%1.2f units”. There is also an indicator string that may be somewhere
+ * else (like on the slider itself) that also accepts a format string like
+ * units. Label, Icon Unit and Indicator strings/objects are optional.
+ *
+ * A slider may be inverted which means values invert, with high vales being
+ * on the left or top and low values on the right or bottom (as opposed to
+ * normally being low on the left or top and high on the bottom and right).
+ *
+ * The slider should have its minimum and maximum values set by the
+ * application with  elm_slider_min_max_set() and value should also be set by
+ * the application before use with  elm_slider_value_set(). The span of the
+ * slider is its length (horizontally or vertically). This will be scaled by
+ * the object or applications scaling factor. At any point code can query the
+ * slider for its value with elm_slider_value_get().
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *slider;
+   Evas_Object *icon;
+   Evas_Object *end;
+   Evas_Object *spacer;
+   const char *label;
+   const char *units;
+   const char *indicator;
+   const char *(*indicator_format_func)(double val);
+   Eina_Bool horizontal : 1;
+   Eina_Bool inverted : 1;
+   Eina_Bool indicator_show : 1;
+   double val, val_min, val_max;
+   Ecore_Timer *delay;
+   Evas_Coord size;
+};
+
+#define ELM_SLIDER_INVERTED_FACTOR (-1.0)
+
+static const char *widtype = NULL;
+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 _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 _units_set(Evas_Object *obj);
+static void _val_set(Evas_Object *obj);
+static void _indicator_set(Evas_Object *obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _drag_up(void *data, Evas_Object *obj,
+                    const char *emission, const char *source);
+static void _drag_down(void *data, Evas_Object *obj,
+                    const char *emission, const char *source);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+static void _spacer_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
+
+static const char SIG_CHANGED[] = "changed";
+static const char SIG_DELAY_CHANGED[] = "delay,changed";
+static const char SIG_DRAG_START[] = "slider,drag,start";
+static const char SIG_DRAG_STOP[] = "slider,drag,stop";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CHANGED, ""},
+  {SIG_DELAY_CHANGED, ""},
+  {SIG_DRAG_START, ""},
+  {SIG_DRAG_STOP, ""},
+  {NULL, NULL}
+};
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   Evas_Event_Mouse_Wheel *mev;
+   Evas_Event_Key_Down *ev;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+
+   if (type == EVAS_CALLBACK_KEY_DOWN) goto key_down;
+   else if (type != EVAS_CALLBACK_MOUSE_WHEEL) return EINA_FALSE;
+
+   mev = event_info;
+   if (mev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+
+   if (mev->z < 0) _drag_up(obj, NULL, NULL, NULL);
+   else _drag_down(obj, NULL, NULL, NULL);
+   mev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+
+  key_down:
+   ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+   if ((!strcmp(ev->keyname, "Left"))
+       || (!strcmp(ev->keyname, "KP_Left")))
+     {
+        if (!wd->horizontal) return EINA_FALSE;
+        if (!wd->inverted) _drag_down(obj, NULL, NULL, NULL);
+        else _drag_up(obj, NULL, NULL, NULL);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "Right"))
+            || (!strcmp(ev->keyname, "KP_Right")))
+     {
+        if (!wd->horizontal) return EINA_FALSE;
+        if (!wd->inverted) _drag_up(obj, NULL, NULL, NULL);
+        else _drag_down(obj, NULL, NULL, NULL);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
+     {
+        if (wd->horizontal) return EINA_FALSE;
+        if (wd->inverted) _drag_up(obj, NULL, NULL, NULL);
+        else _drag_down(obj, NULL, NULL, NULL);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
+     {
+        if (wd->horizontal) return EINA_FALSE;
+        if (wd->inverted) _drag_down(obj, NULL, NULL, NULL);
+        else _drag_up(obj, NULL, NULL, NULL);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   else return EINA_FALSE;
+}
+
+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);
+   if (wd->indicator) eina_stringshare_del(wd->units);
+   if (wd->delay) ecore_timer_del(wd->delay);
+   free(wd);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->slider, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->slider, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->slider, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->slider, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->horizontal)
+     _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", elm_widget_style_get(obj));
+   else
+     _elm_theme_object_set(obj, wd->slider, "slider", "vertical", elm_widget_style_get(obj));
+   if (wd->icon)
+     {
+        edje_object_part_swallow(wd->slider, "elm.swallow.content", wd->icon);
+        edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
+     }
+   if (wd->end)
+     edje_object_signal_emit(wd->slider, "elm,state,end,visible", "elm");
+   else
+     edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
+   if (wd->label)
+     {
+        edje_object_part_text_set(wd->slider, "elm.text", wd->label);
+        edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
+     }
+   
+   if (wd->units)
+     edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
+   
+   if (wd->horizontal)
+     evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
+   else
+     evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
+   
+   if (wd->inverted)
+      edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
+   
+   edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
+   _units_set(obj);
+   _indicator_set(obj);
+   edje_object_message_signal_process(wd->slider);
+   edje_object_scale_set(wd->slider, elm_widget_scale_get(obj) * _elm_config->scale);
+   _val_set(obj);
+   _sizing_eval(obj);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (elm_widget_disabled_get(obj))
+      edje_object_signal_emit(wd->slider, "elm,state,disabled", "elm");
+   else
+      edje_object_signal_emit(wd->slider, "elm,state,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;
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->slider, &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_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if ((obj != wd->icon) && (obj != wd->end)) 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;
+   if (sub == wd->icon)
+     {
+       edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
+       evas_object_event_callback_del_full
+         (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+       wd->icon = NULL;
+       edje_object_message_signal_process(wd->slider);
+       _sizing_eval(obj);
+     }
+   if (sub == wd->end)
+     {
+        edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
+        evas_object_event_callback_del_full(sub,
+                                            EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                            _changed_size_hints, obj);
+        wd->end = NULL;
+        edje_object_message_signal_process(wd->slider);
+        _sizing_eval(obj);
+     }
+}
+
+static Eina_Bool
+_delay_change(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->delay = NULL;
+   evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, NULL);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_val_fetch(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double posx = 0.0, posy = 0.0, pos = 0.0, val;
+   if (!wd) return;
+   edje_object_part_drag_value_get(wd->slider, "elm.dragable.slider",
+                                  &posx, &posy);
+   if (wd->horizontal) pos = posx;
+   else pos = posy;
+   if (wd->inverted) pos = 1.0 - pos;
+   val = (pos * (wd->val_max - wd->val_min)) + wd->val_min;
+   if (val != wd->val)
+     {
+       wd->val = val;
+       evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
+       if (wd->delay) ecore_timer_del(wd->delay);
+       wd->delay = ecore_timer_add(0.2, _delay_change, obj);
+     }
+}
+
+static void
+_val_set(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double pos;
+   if (!wd) return;
+   if (wd->val_max > wd->val_min)
+     pos = (wd->val - wd->val_min) / (wd->val_max - wd->val_min);
+   else
+     pos = 0.0;
+   if (pos < 0.0) pos = 0.0;
+   else if (pos > 1.0) pos = 1.0;
+   if (wd->inverted) pos = 1.0 - pos;
+   edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", pos, pos);
+}
+
+static void
+_units_set(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->units)
+     {
+       char buf[1024];
+
+       snprintf(buf, sizeof(buf), wd->units, wd->val);
+       edje_object_part_text_set(wd->slider, "elm.units", buf);
+     }
+   else
+     edje_object_part_text_set(wd->slider, "elm.units", NULL);
+}
+
+static void
+_indicator_set(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->indicator_format_func)
+     {
+       const char *buf;
+       buf = wd->indicator_format_func(wd->val);
+       edje_object_part_text_set(wd->slider, "elm.indicator", buf);
+     }
+   else if (wd->indicator)
+     {
+       char buf[1024];
+       snprintf(buf, sizeof(buf), wd->indicator, wd->val);
+       edje_object_part_text_set(wd->slider, "elm.indicator", buf);
+     }
+   else
+     edje_object_part_text_set(wd->slider, "elm.indicator", NULL);
+}
+
+static void
+_drag(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _val_fetch(data);
+   _units_set(data);
+   _indicator_set(data);
+}
+
+static void
+_drag_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _val_fetch(data);
+   evas_object_smart_callback_call(data, SIG_DRAG_START, NULL);
+   _units_set(data);
+   _indicator_set(data);
+   elm_widget_scroll_hold_push(data);
+}
+
+static void
+_drag_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _val_fetch(data);
+   evas_object_smart_callback_call(data, SIG_DRAG_STOP, NULL);
+   _units_set(data);
+   _indicator_set(data);
+   elm_widget_scroll_hold_pop(data);
+}
+
+static void
+_drag_step(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _val_fetch(data);
+   _units_set(data);
+   _indicator_set(data);
+}
+
+static void
+_drag_up(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   double step;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(data);
+   step = 0.05;
+
+   if (wd->inverted) step *= ELM_SLIDER_INVERTED_FACTOR;
+
+   edje_object_part_drag_step(wd->slider, "elm.dragable.slider", step, step);
+}
+
+static void
+_drag_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   double step;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(data);
+   step = -0.05;
+
+   if (wd->inverted) step *= ELM_SLIDER_INVERTED_FACTOR;
+
+   edje_object_part_drag_step(wd->slider, "elm.dragable.slider", step, step);
+}
+
+static void
+_spacer_cb(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord x, y, w, h;
+   double button_x, button_y;
+   
+   evas_object_geometry_get(wd->spacer, &x, &y, &w, &h);
+   edje_object_part_drag_value_get(wd->slider, "elm.dragable.slider", &button_x, &button_y);
+   if (wd->horizontal)
+     {
+        button_x = ((double)ev->output.x - (double)x) / (double)w;
+        if (button_x > 1) button_x = 1;
+        if (button_x < 0) button_x = 0;
+     }
+   else 
+     {
+        button_y = ((double)ev->output.y - (double)y) / (double)h;
+        if (button_y > 1) button_y = 1;
+        if (button_y < 0) button_y = 0;
+     }
+   edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", button_x, button_y);
+   evas_event_feed_mouse_cancel(e, 0, NULL);
+   evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, 0, NULL);  
+}
+
+/**
+ * Add a new slider to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Slider
+ */
+EAPI Evas_Object *
+elm_slider_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "slider");
+   elm_widget_type_set(obj, "slider");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->horizontal = EINA_TRUE;
+   wd->indicator_show = EINA_TRUE;
+   wd->val = 0.0;
+   wd->val_min = 0.0;
+   wd->val_max = 1.0;
+
+   wd->slider = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", "default");
+   elm_widget_resize_object_set(obj, wd->slider);
+   edje_object_signal_callback_add(wd->slider, "drag", "*", _drag, obj);
+   edje_object_signal_callback_add(wd->slider, "drag,start", "*", _drag_start, obj);
+   edje_object_signal_callback_add(wd->slider, "drag,stop", "*", _drag_stop, obj);
+   edje_object_signal_callback_add(wd->slider, "drag,step", "*", _drag_step, obj);
+   edje_object_signal_callback_add(wd->slider, "drag,page", "*", _drag_stop, obj);
+//   edje_object_signal_callback_add(wd->slider, "drag,set", "*", _drag_stop, obj);
+   edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", 0.0, 0.0);
+
+   wd->spacer = evas_object_rectangle_add(e);
+   evas_object_color_set(wd->spacer, 0, 0, 0, 0);
+   evas_object_pass_events_set(wd->spacer, EINA_TRUE);
+   elm_widget_sub_object_add(obj, wd->spacer);
+   edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
+   evas_object_event_callback_add(wd->spacer, EVAS_CALLBACK_MOUSE_DOWN, _spacer_cb, obj);
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Set the label of the slider
+ *
+ * @param obj The slider object
+ * @param label The text label string in UTF-8
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_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);
+   if (label)
+     {
+       edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
+       edje_object_message_signal_process(wd->slider);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->slider, "elm,state,text,hidden", "elm");
+       edje_object_message_signal_process(wd->slider);
+     }
+   edje_object_part_text_set(wd->slider, "elm.text", label);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the label of the slider
+ *
+ * @param obj The slider object
+ * @return The text label string in UTF-8
+ *
+ * @ingroup Slider
+ */
+EAPI const char *
+elm_slider_label_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->label;
+}
+
+/**
+ * Set the icon object (leftmost widget) of the slider object.
+ *
+ * Once the icon object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_slider_icon_unset() function.
+ *
+ * @param obj The slider object
+ * @param icon The icon object
+ *
+ * @note If the object being set does not have minimum size hints set,
+ * it won't get properly displayed.
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_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);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->slider, "elm.swallow.icon", icon);
+       edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->slider);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Unset the leftmost widget of the slider, unparenting and
+ * returning it.
+ *
+ * @param obj The slider object
+ * @return the previously set icon sub-object of this slider, on
+ * success.
+ *
+ * @see elm_slider_icon_set()
+ *
+ * @ingroup Slider
+ */
+EAPI Evas_Object *
+elm_slider_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *ret = NULL;
+   if (!wd) return NULL;
+   if (wd->icon)
+     {
+       elm_widget_sub_object_del(obj, wd->icon);
+       ret = wd->icon;
+       edje_object_part_unswallow(wd->slider, wd->icon);
+       edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
+       wd->icon = NULL;
+       _sizing_eval(obj);
+     }
+   return ret;
+}
+
+/**
+ * Get the icon object of the slider object. This object is owned by
+ * the scrolled entry and should not be modified.
+ *
+ * @param obj The slider object
+ * @return The icon object
+ *
+ * @ingroup Slider
+ */
+EAPI Evas_Object *
+elm_slider_icon_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->icon;
+}
+
+/**
+ * Set the length of the dragable region of the slider
+ *
+ * This sets the minimum width or height (depending on orientation) of the
+ * area of the slider that allows the slider to be dragged around. This in
+ * turn affects the objects minimum size (along with icon label and unit
+ * text). Note that this will also get multiplied by the scale factor.
+ *
+ * @param obj The slider object
+ * @param size The length of the slider area
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_span_size_set(Evas_Object *obj, Evas_Coord size)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->size == size) return;
+   wd->size = size;
+   if (wd->horizontal)
+     evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
+   else
+     evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
+   if (wd->indicator_show)
+       edje_object_signal_emit(wd->slider, "elm,state,val,show", "elm");
+   else
+       edje_object_signal_emit(wd->slider, "elm,state,val,hide", "elm");
+   edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the length of the dragable region of the slider
+ *
+ * This gets the minimum width or height (depending on orientation) of
+ * the area of the slider that allows the slider to be dragged
+ * around. Note that this will also get multiplied by the scale
+ * factor.
+ *
+ * @param obj The slider object
+ * @return The length of the slider area
+ *
+ * @ingroup Slider
+ */
+EAPI Evas_Coord
+elm_slider_span_size_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->size;
+}
+
+/**
+ * Set the format string of the unit area
+ *
+ * If NULL, this disabls the unit area display. If not it sets the format
+ * string for the unit text. The unit text is provided a floating point
+ * value, so the unit text can display up to 1 floating point value. Note that
+ * this is optional. Use a format string such as "%1.2f meters" for example.
+ *
+ * @param obj The slider object
+ * @param units The format string for the units display
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_unit_format_set(Evas_Object *obj, const char *units)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->units, units);
+   if (units)
+     {
+       edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
+       edje_object_message_signal_process(wd->slider);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->slider, "elm,state,units,hidden", "elm");
+       edje_object_message_signal_process(wd->slider);
+     }
+   _units_set(obj);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the format string for the unit area
+ *
+ * The slider may also display a value (the value of the slider) somewhere
+ * (for example above the slider knob that is dragged around). This sets the
+ * format string for this. See elm_slider_unit_format_set() for more
+ * information on how this works.
+ *
+ * @param obj The slider object
+ * @return The format string for the unit display.
+ *
+ * @ingroup Slider
+ */
+EAPI const char *
+elm_slider_unit_format_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->units;
+}
+
+/**
+ * Set the format string for the indicator area
+ *
+ * The slider may also display a value (the value of the slider) somewhere
+ * (for example above the slider knob that is dragged around). This sets the
+ * format string for this. See elm_slider_unit_format_set() for more
+ * information on how this works.
+ *
+ * @param obj The slider object
+ * @param indicator The format string for the indicator display
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->indicator, indicator);
+   _indicator_set(obj);
+}
+
+/**
+ * Get the format string for the indicator area
+ *
+ * The slider may also display a value (the value of the slider) somewhere
+ * (for example above the slider knob that is dragged around). This sets the
+ * format string for this. See elm_slider_indicator_format_set() for more
+ * information on how this works.
+ *
+ * @param obj The slider object
+ * @return The format string for the indicator display.
+ *
+ * @ingroup Slider
+ */
+EAPI const char *
+elm_slider_indicator_format_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->indicator;
+}
+
+/**
+ * Set orientation of the slider
+ *
+ * @param obj The slider object
+ * @param horizontal If set, the slider will be horizontal
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   horizontal = !!horizontal;
+   if (wd->horizontal == horizontal) return;
+   wd->horizontal = horizontal;
+   _theme_hook(obj);
+}
+
+/**
+ * Get orientation of the slider
+ *
+ * @param obj The slider object
+ * @return If @c EINA_TRUE the slider will be horizontal, else it is
+ *         vertical.
+ * @ingroup Slider
+ */
+EAPI Eina_Bool
+elm_slider_horizontal_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->horizontal;
+}
+
+/**
+ * Set the minimum and maximum values for the slider
+ *
+ * Maximum mut be greater than minimum.
+ *
+ * @param obj The slider object
+ * @param min The minimum value
+ * @param max The maximum value
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_min_max_set(Evas_Object *obj, double min, double max)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((wd->val_min == min) && (wd->val_max == max)) return;
+   wd->val_min = min;
+   wd->val_max = max;
+   if (wd->val < wd->val_min) wd->val = wd->val_min;
+   if (wd->val > wd->val_max) wd->val = wd->val_max;
+   _val_set(obj);
+   _units_set(obj);
+   _indicator_set(obj);
+}
+
+/**
+ * Get the minimum and maximum values for the slider
+ *
+ * @param obj The slider object
+ * @param min The pointer to store minimum value, may be @c NULL.
+ * @param max The pointer to store maximum value, may be @c NULL.
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_min_max_get(const Evas_Object *obj, double *min, double *max)
+{
+   if (min) *min = 0.0;
+   if (max) *max = 0.0;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (min) *min = wd->val_min;
+   if (max) *max = wd->val_max;
+}
+
+/**
+ * Set the value the slider indicates
+ *
+ * @param obj The slider object
+ * @param val The value (must be between min and max for the slider)
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_value_set(Evas_Object *obj, double val)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->val == val) return;
+   wd->val = val;
+   if (wd->val < wd->val_min) wd->val = wd->val_min;
+   if (wd->val > wd->val_max) wd->val = wd->val_max;
+   _val_set(obj);
+   _units_set(obj);
+   _indicator_set(obj);
+}
+
+/**
+ * Get the value the slider has
+ *
+ * @param obj The slider object
+ * @return The value of the slider
+ *
+ * @ingroup Slider
+ */
+EAPI double
+elm_slider_value_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->val;
+}
+
+/**
+ * Invert the slider display
+ *
+ * Normally the slider will display and interpret values from low to high
+ * and when horizontal that is left to right. When vertical that is top
+ * to bottom. This inverts this (so from right to left or bottom to top) if
+ * inverted is set to 1.
+ *
+ * @param obj The slider object
+ * @param inverted The inverted flag. 1 == inverted, 0 == normal
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_inverted_set(Evas_Object *obj, Eina_Bool inverted)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   inverted = !!inverted;
+   if (wd->inverted == inverted) return;
+   wd->inverted = inverted;
+   if (wd->inverted)
+     edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
+   else
+     edje_object_signal_emit(wd->slider, "elm,state,inverted,off", "elm");
+   edje_object_message_signal_process(wd->slider);
+   _val_set(obj);
+   _units_set(obj);
+   _indicator_set(obj);
+}
+
+/**
+ * Get if the slider display is inverted (backwards)
+ *
+ * @param obj The slider object
+ * @return If @c EINA_TRUE the slider will be inverted.
+ * @ingroup Slider
+ */
+EAPI Eina_Bool
+elm_slider_inverted_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->inverted;
+}
+
+/**
+ * Set the format function pointer for the inducator area
+ *
+ * Set the callback function to format the indicator string.
+ * See elm_slider_indicator_format_set() for more info on how this works.
+ *
+ * @param obj The slider object
+ * @param indicator The format string for the indicator display
+ * @param func The indicator format function
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_indicator_format_function_set(Evas_Object *obj, const char *(*func)(double val))
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->indicator_format_func = func;
+   _indicator_set(obj);
+}
+
+/**
+ * Set the end object (rightmost widget) of the slider object.
+ *
+ * Once the end object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_button_end_unset() function.
+ *
+ * @param obj The slider object
+ * @param end The end object
+ *
+ * @note If the object being set does not have minimum size hints set,
+ * it won't get properly displayed.
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_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->slider, "elm.swallow.end", end);
+       edje_object_signal_emit(wd->slider, "elm,state,end,visible", "elm");
+       edje_object_message_signal_process(wd->slider);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Unset the rightmost widget of the slider, unparenting and
+ * returning it.
+ *
+ * @param obj The slider object
+ * @return the previously set end sub-object of this slider, on
+ * success.
+ *
+ * @see elm_slider_end_set()
+ *
+ * @ingroup Slider
+ */
+EAPI Evas_Object *
+elm_slider_end_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *ret = NULL;
+   if (!wd) return NULL;
+   if (wd->end)
+     {
+       elm_widget_sub_object_del(obj, wd->end);
+       ret = wd->end;
+       edje_object_part_unswallow(wd->slider, wd->end);
+       edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
+       wd->end = NULL;
+       _sizing_eval(obj);
+     }
+   return ret;
+}
+
+/**
+ * Get the end icon object of the slider object. This object is owned
+ * by the scrolled entry and should not be modified.
+ *
+ * @param obj The slider object
+ * @return The end icon object
+ *
+ * @ingroup Slider
+ */
+EAPI Evas_Object *
+elm_slider_end_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->end;
+}
+
+/**
+ * Set whether to the slider indicator (augmented knob) at all.
+ *
+ * @param obj The slider object
+ * @param show @c EINA_TRUE will make it show it, @c EINA_FALSE will
+ * let the knob alwayes at default size.
+ *
+ * @note It will conflict with elm_slider_indicator_format_set(), if
+ * you wanted those effects.
+ *
+ * @ingroup Slider
+ */
+EAPI void
+elm_slider_indicator_show_set(Evas_Object *obj, Eina_Bool show)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (show) {
+      wd->indicator_show = EINA_TRUE;
+      edje_object_signal_emit(wd->slider, "elm,state,val,show", "elm");
+   }
+   else {
+      wd->indicator_show = EINA_FALSE;
+      edje_object_signal_emit(wd->slider, "elm,state,val,hide", "elm");
+   }
+}
+
+/**
+ * Get the state of indicator in the slider (if it's being shown or
+ * not).
+ *
+ * @param obj The slider object
+ * @return @c EINA_TRUE if the indicator is being shown, @c EINA_FALSE
+ * otherwise.
+ *
+ *  @ingroup Slider
+ */
+EAPI Eina_Bool
+elm_slider_indicator_show_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->indicator_show;
+}
+
diff --git a/src/lib/elm_slideshow.c b/src/lib/elm_slideshow.c
new file mode 100644 (file)
index 0000000..79a2b80
--- /dev/null
@@ -0,0 +1,798 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Slideshow slideshow
+ *
+ * This object display a list of object (generally a list of images) and some actions like
+ * next/previous are used to navigate. The animations are defined in the theme,
+ * consequently new animations can be added without having to update the
+ * applications.
+ *
+ * The slideshow use 2 callbacks to create and delete the objects displayed. When an item
+ * is displayed the function itc->func.get() is called. This function should create the object,
+ * for example the object can be an evas_object_image or a photocam. When a object is no more
+ * displayed the function itc->func.del() is called, the user can delete the dana associated to the item.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Elm_Slideshow_Item
+{
+   Elm_Widget_Item base;
+
+   Eina_List *l, *l_built;
+
+   const Elm_Slideshow_Item_Class *itc;
+};
+
+struct _Widget_Data
+{
+   Evas_Object *slideshow;
+
+   // list of Elm_Slideshow_Item*
+   Eina_List *items;
+   Eina_List *items_built;
+
+   Elm_Slideshow_Item *current;
+   Elm_Slideshow_Item *previous;
+
+   Eina_List *transitions;
+   const char *transition;
+
+   Ecore_Timer *timer;
+   double timeout;
+   Eina_Bool loop:1;
+
+   struct {
+          const char *current;
+          Eina_List *list; //list of const char *
+   } layout;
+};
+
+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 Eina_Bool _timer_cb(void *data);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+   if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
+     {
+        elm_slideshow_previous(obj);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
+     {
+        elm_slideshow_next(obj);
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   if ((!strcmp(ev->keyname, "Return")) ||
+       (!strcmp(ev->keyname, "KP_Enter")) ||
+       (!strcmp(ev->keyname, "space")))
+     {
+        if (wd->timeout)
+          {
+             if (wd->timer)
+               {
+                  ecore_timer_del(wd->timer);
+                  wd->timer = NULL;
+               }
+             else
+               elm_slideshow_timeout_set(obj, wd->timeout);
+          }
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   const char *layout;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_slideshow_clear(obj);
+   elm_widget_stringlist_free(wd->transitions);
+   if (wd->timer) ecore_timer_del(wd->timer);
+   EINA_LIST_FREE(wd->layout.list, layout)
+          eina_stringshare_del(layout);
+   free(wd);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->slideshow, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->slideshow, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->slideshow, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->slideshow, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->slideshow, "slideshow", "base", elm_widget_style_get(obj));
+   edje_object_scale_set(wd->slideshow, 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;
+   if (!wd) return;
+   edje_object_size_min_calc(wd->slideshow, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, minw, minh);
+}
+
+
+static Elm_Slideshow_Item* _item_prev_get(Elm_Slideshow_Item* item)
+{
+       Widget_Data *wd = elm_widget_data_get(item->base.widget);
+       Elm_Slideshow_Item* prev = eina_list_data_get(eina_list_prev(item->l));
+       if((!prev) && (wd->loop))
+               prev = eina_list_data_get(eina_list_last(item->l));
+       return prev;
+}
+static Elm_Slideshow_Item* _item_next_get(Elm_Slideshow_Item* item)
+{
+       Widget_Data *wd = elm_widget_data_get(item->base.widget);
+       Elm_Slideshow_Item* next = eina_list_data_get(eina_list_next(item->l));
+       if((!next) && (wd->loop))
+               next = eina_list_data_get(wd->items);
+       return next;
+}
+
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_sub_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   ;
+}
+
+static void
+_item_realize(Elm_Slideshow_Item *item)
+{
+   Elm_Slideshow_Item *_item;
+   Evas_Object *obj = item->base.widget;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   if ((!item->base.view) && (item->itc->func.get))
+     {
+        item->base.view = item->itc->func.get((void*)item->base.data, obj);
+        evas_object_smart_member_add(item->base.view, obj);
+        item->l_built = eina_list_append(NULL, item);
+        wd->items_built = eina_list_merge(wd->items_built, item->l_built);
+        evas_object_hide(item->base.view);
+     }
+   else if (item->l_built)
+     wd->items_built = eina_list_demote_list(wd->items_built, item->l_built);
+
+   //pre-create previous and next item
+   _item = _item_next_get(item);
+   if ((_item) && (!_item->base.view) && (_item->itc->func.get))
+     {
+        _item->base.view = _item->itc->func.get((void*)_item->base.data, obj);
+        evas_object_smart_member_add(_item->base.view, obj);
+        _item->l_built = eina_list_append(NULL, _item);
+        wd->items_built = eina_list_merge(wd->items_built, _item->l_built);
+        evas_object_hide(_item->base.view);
+     }
+   else if ((_item) && (_item->l_built))
+     wd->items_built = eina_list_demote_list(wd->items_built, _item->l_built);
+
+   _item = _item_prev_get(item);
+   if ((_item) && (!_item->base.view) && (_item->itc->func.get))
+     {
+        _item->base.view = _item->itc->func.get((void*)_item->base.data, obj);
+        evas_object_smart_member_add(_item->base.view, obj);
+        _item->l_built = eina_list_append(NULL, _item);
+        wd->items_built = eina_list_merge(wd->items_built, _item->l_built);
+        evas_object_hide(_item->base.view);
+     }
+   else if ((_item) && (_item->l_built))
+     wd->items_built = eina_list_demote_list(wd->items_built, _item->l_built);
+
+   //delete unused items
+   while (eina_list_count(wd->items_built) > 3)
+     {
+        _item = eina_list_data_get(wd->items_built);
+        wd->items_built = eina_list_remove_list(wd->items_built, wd->items_built);
+        if(item->itc->func.del)
+          item->itc->func.del((void*)item->base.data, _item->base.view);
+        evas_object_del(_item->base.view);
+        _item->base.view = NULL;
+     }
+}
+
+static void
+_end(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+       Elm_Slideshow_Item *item;
+       Widget_Data *wd = elm_widget_data_get(data);
+       if (!wd) return;
+
+       item = wd->previous;
+       if(item)
+       {
+               edje_object_part_unswallow(NULL, item->base.view);
+               evas_object_hide(item->base.view);
+               wd->previous = NULL;
+       }
+
+
+       item = wd->current;
+       if ((!item) || (!item->base.view)) return;
+
+       _item_realize(item);
+       edje_object_part_unswallow(NULL, item->base.view);
+       evas_object_show(item->base.view);
+
+       edje_object_signal_emit(wd->slideshow, "anim,end", "slideshow");
+       edje_object_part_swallow(wd->slideshow, "elm.swallow.1", item->base.view);
+}
+
+
+static Eina_Bool
+_timer_cb(void *data)
+{
+   Evas_Object *obj = data;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->timer = NULL;
+   elm_slideshow_next(obj);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+
+
+/**
+ * Add a new slideshow to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Slideshow
+ */
+EAPI Evas_Object *
+elm_slideshow_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "slideshow");
+   elm_widget_type_set(obj, "slideshow");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->current = NULL;
+   wd->previous = NULL;
+
+   wd->slideshow = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->slideshow, "slideshow", "base", "default");
+   evas_object_smart_member_add(wd->slideshow, obj);
+   elm_widget_resize_object_set(obj, wd->slideshow);
+   evas_object_show(wd->slideshow);
+
+   wd->transitions = elm_widget_stringlist_get(edje_object_data_get(wd->slideshow, "transitions"));
+   if (eina_list_count(wd->transitions) > 0)
+     wd->transition = eina_stringshare_add(eina_list_data_get(wd->transitions));
+
+   wd->layout.list = elm_widget_stringlist_get(edje_object_data_get(wd->slideshow, "layouts"));
+   if (eina_list_count(wd->layout.list) > 0)
+       wd->layout.current = eina_list_data_get(wd->layout.list);
+
+   edje_object_signal_callback_add(wd->slideshow, "end", "slideshow", _end, obj);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Add a object in the list. The object can be a evas object image or a elm photo for example.
+ *
+ * @param obj The slideshow object
+ * @aram itc Callbacks used to create the object and delete the data associated when the item is deleted.
+ * @param data Data used by the user to identified the item
+ * @return Returns The slideshow item
+ *
+ * @ingroup Slideshow
+ */
+EAPI Elm_Slideshow_Item*
+elm_slideshow_item_add(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data)
+{
+   Elm_Slideshow_Item *item;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return NULL;
+   item = elm_widget_item_new(obj, Elm_Slideshow_Item);
+   item->base.data = data;
+   item->itc = itc;
+   item->l = eina_list_append(item->l, item);
+
+   wd->items = eina_list_merge(wd->items, item->l);
+
+   if (!wd->current) elm_slideshow_show(item);
+
+   return item;
+}
+
+/**
+ * Go to the item
+ *
+ * @param obj The slideshow object
+ * @param item The item
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_show(Elm_Slideshow_Item *item)
+{
+   char buf[1024];
+   Elm_Slideshow_Item *next = NULL;
+   Widget_Data *wd;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd)
+     return;
+   if (item == wd->current)
+     return;
+
+   next = item;
+   evas_object_smart_callback_call(item->base.widget, "changed", next);
+   _end(item->base.widget, item->base.widget, NULL, NULL);
+
+   if (wd->timer) ecore_timer_del(wd->timer);
+   if (wd->timeout > 0.0)
+          wd->timer = ecore_timer_add(wd->timeout, _timer_cb, item->base.widget);
+   _item_realize(next);
+   edje_object_part_swallow(wd->slideshow, "elm.swallow.2", next->base.view);
+   evas_object_show(next->base.view);
+   snprintf(buf, sizeof(buf), "%s,next", wd->transition);
+   edje_object_signal_emit(wd->slideshow, buf, "slideshow");
+   wd->previous = wd->current;
+   wd->current = next;
+}
+
+/**
+ * Go to the next item
+ *
+ * @param obj The slideshow object
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_next(Evas_Object *obj)
+{
+   char buf[1024];
+   Elm_Slideshow_Item *next = NULL;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   
+   if (wd->current)
+          next = _item_next_get(wd->current);
+
+   if ((!next) || (next == wd->current)) return;
+   evas_object_smart_callback_call(obj, "changed", next);
+
+   _end(obj, obj, NULL, NULL);
+
+   if (wd->timer) ecore_timer_del(wd->timer);
+   if (wd->timeout > 0.0)
+          wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
+
+   _item_realize(next);
+
+   edje_object_part_swallow(wd->slideshow, "elm.swallow.2", next->base.view);
+   evas_object_show(next->base.view);
+
+   snprintf(buf, sizeof(buf), "%s,next", wd->transition);
+   edje_object_signal_emit(wd->slideshow, buf, "slideshow");
+
+   wd->previous = wd->current;
+   wd->current = next;
+}
+
+/**
+ * Go to the previous item
+ *
+ * @param obj The slideshow object
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_previous(Evas_Object *obj)
+{
+   char buf[1024];
+   Elm_Slideshow_Item *prev = NULL;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+
+   if (wd->current)
+     prev = _item_prev_get(wd->current);
+
+   if ((!prev) ||  (prev == wd->current)) return;
+   evas_object_smart_callback_call(obj, "changed", prev);
+
+   _end(obj, obj, NULL, NULL);
+
+   if (wd->timer) ecore_timer_del(wd->timer);
+   if (wd->timeout > 0.0)
+          wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
+
+   _item_realize(prev);
+
+   edje_object_part_swallow(wd->slideshow, "elm.swallow.2", prev->base.view);
+   evas_object_show(prev->base.view);
+
+   snprintf(buf, 1024, "%s,previous", wd->transition);
+   edje_object_signal_emit(wd->slideshow, buf, "slideshow");
+
+   wd->previous = wd->current;
+   wd->current = prev;
+}
+
+/**
+ * Returns the list of transitions available.
+ *
+ * @param obj The slideshow object
+ * @return Returns the list of transitions (list of const char*)
+ *
+ * @ingroup Slideshow
+ */
+EAPI const Eina_List *
+elm_slideshow_transitions_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->transitions;
+}
+
+/**
+ * Returns the list of layouts available.
+ *
+ * @param obj The slideshow object
+ * @return Returns the list of layout (list of const char*)
+ *
+ * @ingroup Slideshow
+ */
+EAPI const Eina_List *
+elm_slideshow_layouts_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->layout.list;
+}
+
+/**
+ * Set the transition to use
+ *
+ * @param obj The slideshow object
+ * @param transition the new transition
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_transition_set(Evas_Object *obj, const char *transition)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->transition, transition);
+}
+
+/**
+ * Returns the transition to use
+ *
+ * @param obj The slideshow object
+ * @return the transition set
+ *
+ * @ingroup Slideshow
+ */
+EAPI const char *
+elm_slideshow_transition_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->transition;
+}
+
+/**
+ * The slideshow can go to the next item automatically after a few seconds.
+ * This method set the timeout to use. A timeout <=0 disable the timer.
+ *
+ * @param obj The slideshow object
+ * @param timeout The new timeout
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_timeout_set(Evas_Object *obj, double timeout)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->timeout = timeout;
+   if (wd->timer) ecore_timer_del(wd->timer);
+   wd->timer = NULL;
+   if (timeout > 0.0)
+     wd->timer = ecore_timer_add(timeout, _timer_cb, obj);
+}
+
+/**
+ * Returns the timeout value
+ *
+ * @param obj The slideshow object
+ * @return Returns the timeout
+ *
+ * @ingroup Slideshow
+ */
+EAPI double
+elm_slideshow_timeout_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return -1.0;
+   return wd->timeout;
+}
+
+/**
+ * Set if the first item should follow the last and vice versa
+ *
+ * @param obj The slideshow object
+ * @param loop if EINA_TRUE, the first item will follow the last and vice versa
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_loop_set(Evas_Object *obj, Eina_Bool loop)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->loop = loop;
+}
+
+/**
+ * Returns the current layout name
+ *
+ * @param obj The slideshow object
+ * @returns Returns the layout name
+ *
+ * @ingroup Slideshow
+ */
+EAPI const char *
+elm_slideshow_layout_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->layout.current;
+}
+
+/**
+ * Set the layout
+ *
+ * @param obj The slideshow object
+ * @param layout the new layout
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_layout_set(Evas_Object *obj, const char *layout)
+{
+   char buf[PATH_MAX];
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   wd->layout.current = layout;
+   snprintf(buf, sizeof(buf), "layout,%s", layout);
+   edje_object_signal_emit(wd->slideshow, buf, "slideshow");
+}
+
+/**
+ * Return if the first item should follow the last and vice versa
+ *
+ * @param obj The slideshow object
+ * @returns Returns the loop flag
+ *
+ * @ingroup Slideshow
+ */
+EAPI Eina_Bool
+elm_slideshow_loop_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->loop;
+}
+
+/**
+ * Delete all the items
+ *
+ * @param obj The slideshow object
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_clear(Evas_Object *obj)
+{
+       Elm_Slideshow_Item *item;
+       ELM_CHECK_WIDTYPE(obj, widtype);
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       wd->previous = NULL;
+       wd->current = NULL;
+       EINA_LIST_FREE(wd->items_built, item)
+       {
+           if (item->itc->func.del)
+             item->itc->func.del((void*)item->base.data, item->base.view);
+           evas_object_del(item->base.view);
+           item->base.view = NULL;
+       }
+
+       EINA_LIST_FREE(wd->items, item)
+          {
+             elm_widget_item_del(item);
+          }
+}
+
+
+/**
+ * Delete the item
+ *
+ * @param item The slideshow item
+ *
+ * @ingroup Slideshow
+ */
+EAPI void
+elm_slideshow_item_del(Elm_Slideshow_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+       Widget_Data *wd = elm_widget_data_get(item->base.widget);
+       if (!wd) return;
+       if (wd->previous == item) wd->previous = NULL;
+       if (wd->current == item)
+       {
+               Eina_List *l = eina_list_data_find_list(wd->items, item);
+               Eina_List *l2 = eina_list_next(l);
+               wd->current = NULL;
+               if (!l2)
+                       l2 = eina_list_nth_list(wd->items, eina_list_count(wd->items) - 1);
+               if (l2)
+                       elm_slideshow_show(eina_list_data_get(l2));
+       }
+
+       wd->items = eina_list_remove_list(wd->items, item->l);
+       wd->items_built = eina_list_remove_list(wd->items_built, item->l_built);
+
+       if ((item->base.view) && (item->itc->func.del))
+               item->itc->func.del((void*)item->base.data, item->base.view);
+       if (item->base.view)
+               evas_object_del(item->base.view);
+       free(item);
+}
+
+/**
+ * Returns the list of items
+ * @param obj The slideshow object
+ * @return Returns the list of items (list of Elm_Slideshow_Item).
+ *
+ * @ingroup Slideshow
+ */
+EAPI const Eina_List *
+elm_slideshow_items_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->items;
+}
+
+
+/**
+ * Returns the current item displayed
+ *
+ * @param obj The slideshow object
+ * @return Returns the current item displayed
+ *
+ * @ingroup Slideshow
+ */
+EAPI Elm_Slideshow_Item *
+elm_slideshow_item_current_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->current;
+}
+
+/**
+ * Returns the evas object associated to an item
+ *
+ * @param item The slideshow item
+ * @return Returns the evas object associated to this item
+ *
+ * @ingroup Slideshow
+ */
+EAPI Evas_Object *
+elm_slideshow_item_object_get(const Elm_Slideshow_Item * item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->base.view;
+}
+
+/**
+ * Returns the data associated to an item
+ *
+ * @param item The slideshow item
+ * @return Returns the data associated to this item
+ *
+ * @ingroup Slideshow
+ */
+EAPI void *
+elm_slideshow_item_data_get(const Elm_Slideshow_Item * item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_data_get(item);
+}
diff --git a/src/lib/elm_spinner.c b/src/lib/elm_spinner.c
new file mode 100644 (file)
index 0000000..3ce2ea3
--- /dev/null
@@ -0,0 +1,924 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+#include <ctype.h>
+
+/**
+ * @defgroup Spinner
+ *
+ * A spinner is a widget which allows the user to increase or decrease
+ * numeric values. By default the spinner will not wrap and has a label
+ * of "%.0f" (just showing the integer value of the double).
+ *
+ * A spinner has a label that is formatted with floating
+ * point values and thus accepts a printf-style format string, like
+ * “%1.2f units”.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * changed - Whenever the spinner value is changed by the user.
+ *
+ * delay,changed - A short time after the value is changed by the user.
+ * This will be called only when the user stops dragging for a very short
+ * period or when they release their finger/mouse, so it avoids possibly
+ * expensive reactions to the value change.
+ */
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Elm_Spinner_Special_Value Elm_Spinner_Special_Value;
+
+struct _Widget_Data
+{
+   Evas_Object *spinner, *ent;
+   const char *label;
+   double val, val_min, val_max, orig_val, step;
+   double drag_start_pos, spin_speed, interval, first_interval;
+   Ecore_Timer *delay, *spin;
+   Eina_List *special_values;
+   Eina_Bool wrap : 1;
+   Eina_Bool entry_visible : 1;
+   Eina_Bool dragging : 1;
+   Eina_Bool editable : 1;
+};
+
+struct _Elm_Spinner_Special_Value
+{
+   double value;
+   const char *label;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _disable_hook(Evas_Object *obj);
+static void _write_label(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 Eina_Bool _value_set(Evas_Object *obj, double delta);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Elm_Spinner_Special_Value *sv;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->label) eina_stringshare_del(wd->label);
+   if (wd->delay) ecore_timer_del(wd->delay);
+   if (wd->spin) ecore_timer_del(wd->spin);
+   if (wd->special_values)
+     {
+        EINA_LIST_FREE(wd->special_values, sv)
+          {
+             eina_stringshare_del(sv->label);
+             free(sv);
+          }
+     }
+   free(wd);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (elm_widget_disabled_get(obj))
+      edje_object_signal_emit(wd->spinner, "elm,state,disabled", "elm");
+   else
+      edje_object_signal_emit(wd->spinner, "elm,state,enabled", "elm");
+}
+
+static void
+_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(wd->spinner, emission, source);
+}
+
+static void
+_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_callback_add(wd->spinner, emission,
+                                   source, func_cb, data);
+}
+
+static void
+_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   edje_object_signal_callback_del_full(wd->spinner, emission, source,
+                                        func_cb, data);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->spinner, "spinner", "base", elm_widget_style_get(obj));
+   edje_object_part_swallow(wd->spinner, "elm.swallow.entry", wd->ent);
+   _write_label(obj);
+   if (elm_widget_focus_get(obj))
+      edje_object_signal_emit(wd->spinner, "elm,action,focus", "elm");
+   else
+      edje_object_signal_emit(wd->spinner, "elm,action,unfocus", "elm");
+   if (elm_widget_disabled_get(obj))
+      edje_object_signal_emit(wd->spinner, "elm,state,disabled", "elm");
+   edje_object_message_signal_process(wd->spinner);
+   edje_object_scale_set(wd->spinner, elm_widget_scale_get(obj) * _elm_config->scale);
+   _sizing_eval(obj);
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->spinner, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->spinner, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->spinner, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->spinner, EINA_FALSE);
+     }
+}
+
+static Eina_Bool
+_delay_change(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   wd->delay = NULL;
+   evas_object_smart_callback_call(data, "delay,changed", NULL);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_entry_show(Widget_Data *wd)
+{
+   char buf[32], fmt[32] = "%0.f";
+
+   /* try to construct just the format from given label
+    * completely ignoring pre/post words
+    */
+   if (wd->label)
+     {
+        const char *start = strchr(wd->label, '%');
+        while (start)
+          {
+            /* handle %% */
+            if (start[1] != '%')
+              break;
+            else
+              start = strchr(start + 2, '%');
+          }
+
+        if (start)
+          {
+            const char *itr, *end = NULL;
+            for (itr = start + 1; *itr != '\0'; itr++)
+              {
+                 /* allowing '%d' is quite dangerous, remove it? */
+                 if ((*itr == 'd') || (*itr == 'f'))
+                   {
+                      end = itr + 1;
+                      break;
+                   }
+              }
+
+            if ((end) && ((size_t)(end - start + 1) < sizeof(fmt)))
+              {
+                 memcpy(fmt, start, end - start);
+                 fmt[end - start] = '\0';
+              }
+          }
+     }
+   snprintf(buf, sizeof(buf), fmt, wd->val);
+   elm_entry_entry_set(wd->ent, buf);
+}
+
+static void
+_write_label(Evas_Object *obj)
+{
+   Eina_List *l;
+   Elm_Spinner_Special_Value *sv;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char buf[1024];
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->special_values, l, sv)
+     {
+        if (sv->value == wd->val)
+          {
+             snprintf(buf, sizeof(buf), "%s", sv->label);
+             goto apply;
+          }
+     }
+   if (wd->label)
+     snprintf(buf, sizeof(buf), wd->label, wd->val);
+   else
+     snprintf(buf, sizeof(buf), "%.0f", wd->val);
+
+apply:
+   edje_object_part_text_set(wd->spinner, "elm.text", buf);
+   if (wd->entry_visible) _entry_show(wd);
+}
+
+static Eina_Bool 
+_value_set(Evas_Object *obj, double delta)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double new_val;
+   if (!wd) return EINA_FALSE;
+   new_val = wd->val + delta;
+   if (wd->wrap)
+     {
+        while (new_val < wd->val_min)
+          new_val = wd->val_max + new_val + 1 - wd->val_min;
+        while (new_val > wd->val_max)
+          new_val = wd->val_min + new_val - wd->val_max - 1;
+     }
+   else
+     {
+        if (new_val < wd->val_min)
+          new_val = wd->val_min;
+        else if (new_val > wd->val_max)
+          new_val = wd->val_max;
+     }
+
+   if (new_val == wd->val) return EINA_FALSE;
+   wd->val = new_val;
+
+   evas_object_smart_callback_call(obj, "changed", NULL);
+   if (wd->delay) ecore_timer_del(wd->delay);
+   wd->delay = ecore_timer_add(0.2, _delay_change, obj);
+
+   return EINA_TRUE;
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->spinner, &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, -1, -1);
+}
+
+/*
+static void
+_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _sizing_eval(data);
+}
+*/
+
+static void
+_val_set(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   double pos = 0.0;
+   if (!wd) return;
+   if (wd->val_max > wd->val_min)
+     pos = ((wd->val - wd->val_min) / (wd->val_max - wd->val_min));
+   if (pos < 0.0) pos = 0.0;
+   else if (pos > 1.0) pos = 1.0;
+   edje_object_part_drag_value_set(wd->spinner, "elm.dragable.slider", 
+                                   pos, pos);
+}
+
+static void
+_drag(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   double pos = 0.0, offset, delta;
+   if (!wd) return;
+   if (wd->entry_visible) return;
+   edje_object_part_drag_value_get(wd->spinner, "elm.dragable.slider",
+                                  &pos, NULL);
+   offset = wd->step;
+   delta = (pos - wd->drag_start_pos) * offset;
+   if (_value_set(data, delta)) _write_label(data);
+   wd->drag_start_pos = pos;
+   wd->dragging = 1;
+}
+
+static void
+_drag_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   double pos;
+   if (!wd) return;
+   edje_object_part_drag_value_get(wd->spinner, "elm.dragable.slider",
+                                  &pos, NULL);
+   wd->drag_start_pos = pos;
+}
+
+static void
+_drag_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->drag_start_pos = 0;
+   edje_object_part_drag_value_set(wd->spinner, "elm.dragable.slider", 0.0, 0.0);
+}
+
+static void
+_hide_entry(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   edje_object_signal_emit(wd->spinner, "elm,state,inactive", "elm");
+   wd->entry_visible = 0;
+}
+
+static void
+_reset_value(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _hide_entry(obj);
+   elm_spinner_value_set(obj, wd->orig_val);
+}
+
+static void
+_apply_entry_value(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *str;
+   char *end;
+   double val;
+   
+   if (!wd) return;
+   _hide_entry(obj);
+   str = elm_entry_entry_get(wd->ent);
+   if (!str) return;
+   val = strtod(str, &end);
+   if ((*end != '\0') && (!isspace(*end))) return;
+   elm_spinner_value_set(obj, val);
+}
+
+static void
+_toggle_entry(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->dragging)
+     {
+        wd->dragging = 0;
+        return;
+     }
+   if (elm_widget_disabled_get(data)) return;
+   if (!wd->editable) return;
+   if (wd->entry_visible) _apply_entry_value(data);
+   else
+     {
+        wd->orig_val = wd->val;
+       edje_object_signal_emit(wd->spinner, "elm,state,active", "elm");
+        _entry_show(wd);
+        elm_entry_select_all(wd->ent);
+       elm_widget_focus_set(wd->ent, 1);
+        wd->entry_visible = 1;
+     }
+}
+
+static Eina_Bool
+_spin_value(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   if (_value_set(data, wd->spin_speed)) _write_label(data);
+   wd->interval = wd->interval / 1.05;
+   ecore_timer_interval_set(wd->spin, wd->interval);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_val_inc_start(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->spin_speed = wd->step;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _spin_value, obj);
+   _spin_value(obj);
+}
+
+static void
+_val_inc_stop(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->spin_speed = 0;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = NULL;
+}
+
+static void
+_val_dec_start(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->spin_speed = -wd->step;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = ecore_timer_add(wd->interval, _spin_value, obj);
+   _spin_value(obj);
+}
+
+static void
+_val_dec_stop(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->interval = wd->first_interval;
+   wd->spin_speed = 0;
+   if (wd->spin) ecore_timer_del(wd->spin);
+   wd->spin = NULL;
+}
+
+static void
+_button_inc_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->entry_visible)
+     {
+        _reset_value(data);
+        return;
+     }
+   _val_inc_start(data);
+}
+
+static void
+_button_inc_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   _val_inc_stop(data);
+}
+
+static void
+_button_dec_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->entry_visible)
+     {
+        _reset_value(data);
+        return;
+     }
+   _val_dec_start(data);
+}
+
+static void
+_button_dec_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   _val_dec_stop(data);
+}
+
+static void
+_entry_activated(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   _apply_entry_value(data);
+   evas_object_smart_callback_call(data, "changed", NULL);
+   if (wd->delay) ecore_timer_del(wd->delay);
+   wd->delay = ecore_timer_add(0.2, _delay_change, data);
+}
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+   if (type == EVAS_CALLBACK_KEY_DOWN)
+     {
+        Evas_Event_Key_Down *ev = event_info;
+        if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+        else if (!strcmp(ev->keyname, "Left") || !strcmp(ev->keyname, "KP_Left")
+                 || !strcmp(ev->keyname, "Down") || !strcmp(ev->keyname, "KP_Down"))
+          {
+             _val_dec_start(obj);
+             edje_object_signal_emit(wd->spinner, "elm,left,anim,activate", "elm");
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if (!strcmp(ev->keyname, "Right") || !strcmp(ev->keyname, "KP_Right")
+                 || !strcmp(ev->keyname, "Up") || !strcmp(ev->keyname, "KP_Up"))
+          {
+             _val_inc_start(obj);
+             edje_object_signal_emit(wd->spinner, "elm,right,anim,activate", "elm");
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+     }
+   else if (type == EVAS_CALLBACK_KEY_UP)
+     {
+        Evas_Event_Key_Down *ev = event_info;
+        if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+        if (!strcmp(ev->keyname, "Right") || !strcmp(ev->keyname, "KP_Right")
+            || !strcmp(ev->keyname, "Up") || !strcmp(ev->keyname, "KP_Up"))
+          _val_inc_stop(obj);
+        else if (!strcmp(ev->keyname, "Left") || !strcmp(ev->keyname, "KP_Left")
+            || !strcmp(ev->keyname, "Down") || !strcmp(ev->keyname, "KP_Down"))
+          _val_dec_stop(obj);
+        else  return EINA_FALSE;
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+     }
+     return EINA_FALSE;
+}
+
+/**
+ * Add a new spinner to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Spinner
+ */
+EAPI Evas_Object *
+elm_spinner_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "spinner");
+   elm_widget_type_set(obj, "spinner");
+   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_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
+   elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
+   elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->val = 0.0;
+   wd->val_min = 0.0;
+   wd->val_max = 100.0;
+   wd->wrap = 0;
+   wd->step = 1.0;
+   wd->first_interval = 0.85;
+   wd->entry_visible = 0;
+   wd->editable = EINA_TRUE;
+
+   wd->spinner = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->spinner, "spinner", "base", "default");
+   elm_widget_resize_object_set(obj, wd->spinner);
+   edje_object_signal_callback_add(wd->spinner, "drag", "*", _drag, obj);
+   edje_object_signal_callback_add(wd->spinner, "drag,start", "*", 
+                                   _drag_start, obj);
+   edje_object_signal_callback_add(wd->spinner, "drag,stop", "*", 
+                                   _drag_stop, obj);
+   edje_object_signal_callback_add(wd->spinner, "drag,step", "*", 
+                                   _drag_stop, obj);
+   edje_object_signal_callback_add(wd->spinner, "drag,page", "*", 
+                                   _drag_stop, obj);
+
+   edje_object_signal_callback_add(wd->spinner, "elm,action,increment,start", 
+                                   "*", _button_inc_start, obj);
+   edje_object_signal_callback_add(wd->spinner, "elm,action,increment,stop", 
+                                   "*", _button_inc_stop, obj);
+   edje_object_signal_callback_add(wd->spinner, "elm,action,decrement,start", 
+                                   "*", _button_dec_start, obj);
+   edje_object_signal_callback_add(wd->spinner, "elm,action,decrement,stop", 
+                                   "*", _button_dec_stop, obj);
+   edje_object_part_drag_value_set(wd->spinner, "elm.dragable.slider", 
+                                   0.0, 0.0);
+
+   wd->ent = elm_entry_add(obj);
+   elm_entry_single_line_set(wd->ent, 1);
+   evas_object_smart_callback_add(wd->ent, "activated", _entry_activated, obj);
+   edje_object_part_swallow(wd->spinner, "elm.swallow.entry", wd->ent);
+   edje_object_signal_callback_add(wd->spinner, "elm,action,entry,toggle", 
+                                   "*", _toggle_entry, obj);
+
+   _write_label(obj);
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the format string of the label area
+ *
+ * If NULL, this sets the format to "%.0f". If not it sets the format
+ * string for the label text. The label text is provided a floating point
+ * value, so the label text can display up to 1 floating point value. Note that
+ * this is optional. Use a format string such as "%1.2f meters" for example.
+ *
+ * @param obj The spinner object
+ * @param fmt The format string for the label display
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_label_format_set(Evas_Object *obj, const char *fmt)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->label, fmt);
+   _write_label(obj);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the label format of the spinner
+ *
+ * @param obj The spinner object
+ * @return The text label format string in UTF-8
+ *
+ * @ingroup Spinner
+ */
+EAPI const char *
+elm_spinner_label_format_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->label;
+}
+
+/**
+ * Set the minimum and maximum values for the spinner
+ *
+ * Maximum must be greater than minimum.
+ *
+ * @param obj The spinner object
+ * @param min The minimum value
+ * @param max The maximum value
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_min_max_set(Evas_Object *obj, double min, double max)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((wd->val_min == min) && (wd->val_max == max)) return;
+   wd->val_min = min;
+   wd->val_max = max;
+   if (wd->val < wd->val_min) wd->val = wd->val_min;
+   if (wd->val > wd->val_max) wd->val = wd->val_max;
+   _val_set(obj);
+   _write_label(obj);
+}
+
+/**
+ * Get the minimum and maximum values of the spinner
+ *
+ * @param obj The spinner object
+ * @param min The minimum value
+ * @param max The maximum value
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_min_max_get(const Evas_Object *obj, double *min, double *max)
+{
+   if (min) *min = 0.0;
+   if (max) *max = 0.0;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (min) *min = wd->val_min;
+   if (max) *max = wd->val_max;
+}
+
+/**
+ * Set the step for the spinner
+ *
+ * @param obj The spinner object
+ * @param step The step value
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_step_set(Evas_Object *obj, double step)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->step = step;
+}
+
+/**
+ * Get the step of the spinner
+ *
+ * @param obj The spinner object
+ * @return The step value
+ *
+ * @ingroup Spinner
+ */
+EAPI double
+elm_spinner_step_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->step;
+}
+/**
+ * Set the value the spinner indicates
+ *
+ * @param obj The spinner object
+ * @param val The value (must be between min and max for the spinner)
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_value_set(Evas_Object *obj, double val)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->val == val) return;
+   wd->val = val;
+   if (wd->val < wd->val_min) wd->val = wd->val_min;
+   if (wd->val > wd->val_max) wd->val = wd->val_max;
+   _val_set(obj);
+   _write_label(obj);
+}
+
+/**
+ * Get the value the spinner has
+ *
+ * @param obj The spinner object
+ * @return The value of the spinner
+ *
+ * @ingroup Spinner
+ */
+EAPI double
+elm_spinner_value_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->val;
+}
+
+/**
+ * Sets whether the spinner should wrap when it reaches its
+ * minimum/maximum value
+ *
+ * @param obj The spinner object
+ * @param wrap True if it should wrap, false otherwise
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_wrap_set(Evas_Object *obj, Eina_Bool wrap)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->wrap = wrap;
+}
+
+/**
+ * Gets whether the spinner should wrap when it reaches its
+ * minimum/maximum value
+ *
+ * @param obj The spinner object
+ * @return Bool value of wrap option
+ * (0 = disabled, 1 = enabled)
+ *
+ * @ingroup Spinner
+ */
+EAPI Eina_Bool
+elm_spinner_wrap_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->wrap;
+}
+
+/**
+ * Set a special value to display in the place of the numerical one.
+ *
+ * @param obj The spinner object
+ * @param value The value to be replaced
+ * @param label The label to be used
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_special_value_add(Evas_Object *obj, double value, const char *label)
+{
+    Elm_Spinner_Special_Value *sv;
+    ELM_CHECK_WIDTYPE(obj, widtype);
+    Widget_Data *wd = elm_widget_data_get(obj);
+    if (!wd) return;
+
+    sv = calloc(1, sizeof(*sv));
+    if (!sv) return;
+    sv->value = value;
+    sv->label = eina_stringshare_add(label);
+
+    wd->special_values = eina_list_append(wd->special_values, sv);
+    _write_label(obj);
+}
+
+/**
+ * Set whether the spinner can be directly edited by the user or not.
+ * Default is editable.
+ *
+ * @param obj The spinner object
+ * @param editable Bool value of the edit option
+ * (EINA_FALSE = not editable, EINA_TRUE = editable)
+ */
+EAPI void
+elm_spinner_editable_set(Evas_Object *obj, Eina_Bool editable)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->editable = editable;
+}
+
+/**
+ * Gets whether the spinner is editable.
+ *
+ * @param obj The spinner object
+ * @return Bool value of edit option
+ * (EINA_FALSE = not editable, EINA_TRUE = editable)
+ */
+EAPI Eina_Bool
+elm_spinner_editable_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->editable;
+}
+
+/**
+ * Set the interval for the spinner
+ *
+ * @param obj The spinner object
+ * @param interval The interval value in seconds
+ *
+ * The interval value is decreased while the user increments or decrements
+ * the spinner value. The next interval value is the previous interval / 1.05,
+ * so it speed up a bit. Default value is 0.85 seconds.
+ *
+ * @ingroup Spinner
+ */
+EAPI void
+elm_spinner_interval_set(Evas_Object *obj, double interval)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->first_interval = interval;
+}
+
+/**
+ * Get the interval of the spinner
+ *
+ * @param obj The spinner object
+ * @return The value of the first interval in seconds
+ *
+ * The interval value is decreased while the user increments or decrements
+ * the spinner value. The next interval value is the previous interval / 1.05,
+ * so it speed up a bit. Default value is 0.85 seconds.
+ *
+ * @ingroup Spinner
+ */
+EAPI double
+elm_spinner_interval_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0.0;
+   return wd->first_interval;
+}
diff --git a/src/lib/elm_store.c b/src/lib/elm_store.c
new file mode 100644 (file)
index 0000000..dba552b
--- /dev/null
@@ -0,0 +1,754 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#include "elm_priv.h"
+
+#ifndef EFL_HAVE_THREADS
+# error "No thread support. Required." 
+#endif
+
+#ifdef EFL_HAVE_POSIX_THREADS
+# include <pthread.h>
+# define LK(x)  pthread_mutex_t x
+# define LKI(x) pthread_mutex_init(&(x), NULL);
+# define LKD(x) pthread_mutex_destroy(&(x));
+# define LKL(x) pthread_mutex_lock(&(x));
+# define LKU(x) pthread_mutex_unlock(&(x));
+#else /* EFL_HAVE_WIN32_THREADS */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+# define LK(x)  HANDLE x
+# define LKI(x) x = CreateMutex(NULL, FALSE, NULL)
+# define LKD(x) CloseHandle(x)
+# define LKL(x) WaitForSingleObject(x, INFINITE)
+# define LKU(x) ReleaseMutex(x)
+#endif
+
+#define ELM_STORE_MAGIC            0x3f89ea56
+#define ELM_STORE_FILESYSTEM_MAGIC 0x3f89ea57
+#define ELM_STORE_ITEM_MAGIC       0x5afe8c1d
+
+struct _Elm_Store
+{
+  EINA_MAGIC;
+  void         (*free)(Elm_Store *store);
+  struct {
+     void        (*free)(Elm_Store_Item *item);
+  } item;
+  Evas_Object   *genlist;
+  Ecore_Thread  *list_th;
+  Eina_Inlist   *items;
+  Eina_List     *realized;
+  int            realized_count;
+  int            cache_max;
+  struct {
+    struct {
+      Elm_Store_Item_List_Cb     func;
+      void                      *data;
+    } list;
+    struct {
+      Elm_Store_Item_Fetch_Cb    func;
+      void                      *data;
+    } fetch;
+    struct {
+      Elm_Store_Item_Unfetch_Cb  func;
+      void                      *data;
+    } unfetch;
+  } cb;
+  Eina_Bool sorted : 1;
+  Eina_Bool fetch_thread : 1;
+};
+
+struct _Elm_Store_Item
+{
+  EINA_INLIST;
+  EINA_MAGIC;
+  Elm_Store                    *store;
+  Elm_Genlist_Item             *item;
+  Ecore_Thread                 *fetch_th;
+  Ecore_Job                    *eval_job;
+  const Elm_Store_Item_Mapping *mapping;
+  void                         *data;
+  LK(lock);
+  Eina_Bool                     live : 1;
+  Eina_Bool                     was_live : 1;
+  Eina_Bool                     realized : 1;
+  Eina_Bool                     fetched : 1;
+};
+
+struct _Elm_Store_Filesystem
+{
+  Elm_Store base;
+  EINA_MAGIC;
+  const char *dir;
+};
+
+struct _Elm_Store_Item_Filesystem
+{
+  Elm_Store_Item base;
+  const char *path;
+};
+
+static Elm_Genlist_Item_Class _store_item_class;
+
+static void
+_store_cache_trim(Elm_Store *st)
+{
+  while ((st->realized ) &&
+         (((int)eina_list_count(st->realized) - st->realized_count)
+           > st->cache_max))
+    {
+      Elm_Store_Item *sti = st->realized->data;
+      if (sti->realized)
+        {
+          st->realized = eina_list_remove_list(st->realized, st->realized);
+          sti->realized = EINA_FALSE;
+        }
+      LKL(sti->lock);
+      if (!sti->fetched)
+        {
+          LKU(sti->lock);
+          if (sti->fetch_th)
+            {
+              ecore_thread_cancel(sti->fetch_th);
+              sti->fetch_th = NULL;
+            }
+          LKL(sti->lock);
+        }
+      sti->fetched = EINA_FALSE;
+      LKU(sti->lock);
+      if (st->cb.unfetch.func)
+        st->cb.unfetch.func(st->cb.unfetch.data, sti);
+      LKL(sti->lock);
+      sti->data = NULL;
+      LKU(sti->lock);
+    }
+}
+
+static void 
+_store_genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+  Elm_Store *st = data;
+  st->genlist = NULL;
+  if (st->list_th)
+    {
+      ecore_thread_cancel(st->list_th);
+      st->list_th = NULL;
+    }
+  eina_list_free(st->realized);
+  while (st->items)
+    {
+      Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
+      if (sti->eval_job) ecore_job_del(sti->eval_job);
+      if (sti->fetch_th)
+        {
+          ecore_thread_cancel(sti->fetch_th);
+          sti->fetch_th = NULL;
+        }
+      if (sti->store->item.free) sti->store->item.free(sti);
+      if (sti->data)
+        {
+          if (st->cb.unfetch.func)
+            st->cb.unfetch.func(st->cb.unfetch.data, sti);
+          sti->data = NULL;
+        }
+      LKD(sti->lock);
+      free(sti);
+    }
+  // FIXME: kill threads and more
+}
+
+////// **** WARNING ***********************************************************
+////   * This function runs inside a thread outside efl mainloop. Be careful! *
+//     ************************************************************************
+/* TODO: refactor lock part into core? this does not depend on filesystm part */
+static void
+_store_filesystem_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
+{
+  Elm_Store_Item *sti = data;
+  LKL(sti->lock);
+  if (sti->data)
+    {
+      LKU(sti->lock);
+      return;
+    }
+  if (!sti->fetched)
+    {
+      LKU(sti->lock);
+      if (sti->store->cb.fetch.func)
+        sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti);
+      LKL(sti->lock);
+      sti->fetched = EINA_TRUE;
+    }
+  LKU(sti->lock);
+}
+//     ************************************************************************
+////   * End of separate thread function.                                     *
+////// ************************************************************************
+/* TODO: refactor lock part into core? this does not depend on filesystm part */
+static void
+_store_filesystem_fetch_end(void *data, Ecore_Thread *th)
+{
+  Elm_Store_Item *sti = data;
+  LKL(sti->lock);
+  if (sti->data) elm_genlist_item_update(sti->item);
+  LKU(sti->lock);
+  if (th == sti->fetch_th) sti->fetch_th = NULL;
+}
+
+/* TODO: refactor lock part into core? this does not depend on filesystm part */
+static void
+_store_filesystem_fetch_cancel(void *data, Ecore_Thread *th)
+{
+  Elm_Store_Item *sti = data;
+  LKL(sti->lock);
+  if (th == sti->fetch_th) sti->fetch_th = NULL;
+  if (sti->data) elm_genlist_item_update(sti->item);
+  LKU(sti->lock);
+}
+
+static void
+_store_item_eval(void *data)
+{
+  Elm_Store_Item *sti = data;
+  sti->eval_job = NULL;
+  if (sti->live == sti->was_live) return;
+  sti->was_live = sti->live;
+  if (sti->live)
+    {
+      _store_cache_trim(sti->store);
+      if (sti->realized)
+        sti->store->realized = eina_list_remove(sti->store->realized, sti);
+      sti->store->realized = eina_list_append(sti->store->realized, sti);
+      sti->realized = EINA_TRUE;
+      if ((sti->store->fetch_thread) && (!sti->fetch_th))
+        sti->fetch_th = ecore_thread_run(_store_filesystem_fetch_do,
+                                         _store_filesystem_fetch_end,
+                                         _store_filesystem_fetch_cancel,
+                                         sti);
+      else if ((!sti->store->fetch_thread))
+        {
+          _store_filesystem_fetch_do(sti, NULL);
+          _store_filesystem_fetch_end(sti, NULL);
+        }
+    }
+  else
+    {
+      if (sti->fetch_th)
+        {
+          ecore_thread_cancel(sti->fetch_th);
+          sti->fetch_th = NULL;
+        }
+      _store_cache_trim(sti->store);
+    }
+}
+
+static void
+_store_genlist_item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+  Elm_Store *st = data;
+  Elm_Genlist_Item *gli = event_info;
+  Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
+  if (!sti) return;
+  st->realized_count++;
+  sti->live = EINA_TRUE;
+  if (sti->eval_job) ecore_job_del(sti->eval_job);
+  sti->eval_job = ecore_job_add(_store_item_eval, sti);
+}
+
+static void
+_store_genlist_item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+  Elm_Store *st = data;
+  Elm_Genlist_Item *gli = event_info;
+  Elm_Store_Item *sti = elm_genlist_item_data_get(gli);
+  if (!sti) return;
+  st->realized_count--;
+  sti->live = EINA_FALSE;
+  if (sti->eval_job) ecore_job_del(sti->eval_job);
+  sti->eval_job = ecore_job_add(_store_item_eval, sti);
+}
+
+static const Elm_Store_Item_Mapping *
+_store_item_mapping_find(Elm_Store_Item *sti, const char *part)
+{
+  const Elm_Store_Item_Mapping *m;
+  
+  for (m = sti->mapping; m; m ++)
+    {
+      if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
+      if (!strcmp(part, m->part)) return m;
+    }
+  return NULL;
+}
+
+static char *
+_store_item_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
+{
+  Elm_Store_Item *sti = data;
+  const char *s = "";
+  LKL(sti->lock);
+  if (sti->data)
+    {
+      const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
+      if (m)
+        {
+          switch (m->type)
+            {
+            case ELM_STORE_ITEM_MAPPING_LABEL:
+              s = *(char **)(((unsigned char *)sti->data) + m->offset);
+              break;
+            case ELM_STORE_ITEM_MAPPING_CUSTOM:
+              if (m->details.custom.func)
+                s = m->details.custom.func(sti->data, sti, part);
+              break;
+            default:
+              break;
+            }
+        }
+    }
+  LKU(sti->lock);
+  return strdup(s);
+}
+
+static Evas_Object *
+_store_item_icon_get(void *data, Evas_Object *obj, const char *part)
+{
+  Elm_Store_Item *sti = data;
+  LKL(sti->lock);
+  if (sti->data)
+    {
+      const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
+      if (m)
+        {
+          Evas_Object *ic = NULL;
+          const char *s = NULL;
+          
+          switch (m->type)
+            {
+            case ELM_STORE_ITEM_MAPPING_ICON:
+              ic = elm_icon_add(obj);
+              s = *(char **)(((unsigned char *)sti->data) + m->offset);
+              elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
+              evas_object_size_hint_aspect_set(ic, 
+                                               EVAS_ASPECT_CONTROL_VERTICAL, 
+                                               m->details.icon.w,
+                                               m->details.icon.h);
+              elm_icon_smooth_set(ic, m->details.icon.smooth);
+              elm_icon_no_scale_set(ic, m->details.icon.no_scale);
+              elm_icon_scale_set(ic, 
+                                 m->details.icon.scale_up, 
+                                 m->details.icon.scale_down);
+              if (s)
+                {
+                  if (m->details.icon.standard_name)
+                    elm_icon_standard_set(ic, s);
+                  else
+                    elm_icon_file_set(ic, s, NULL);
+                }
+              break;
+            case ELM_STORE_ITEM_MAPPING_PHOTO:
+              ic = elm_icon_add(obj);
+              s = *(char **)(((unsigned char *)sti->data) + m->offset);
+              elm_photo_size_set(ic, m->details.photo.size);
+              if (s)
+                elm_photo_file_set(ic, s);
+              break;
+            case ELM_STORE_ITEM_MAPPING_CUSTOM:
+              if (m->details.custom.func)
+                ic = m->details.custom.func(sti->data, sti, part);
+              break;
+            default:
+              break;
+            }
+          LKU(sti->lock);
+          return ic;
+        }
+    }
+  LKU(sti->lock);
+  return NULL;
+}
+
+static void
+_store_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
+{
+}
+
+////// **** WARNING ***********************************************************
+////   * This function runs inside a thread outside efl mainloop. Be careful! *
+//     ************************************************************************
+static int
+_store_filesystem_sort_cb(void *d1, void *d2)
+{
+  Elm_Store_Item_Info *info1 = d1, *info2 = d2;
+  if ((!info1->sort_id) || (!info2->sort_id)) return 0;
+  return strcoll(info1->sort_id, info2->sort_id);
+}
+
+static void
+_store_filesystem_list_do(void *data, Ecore_Thread *th __UNUSED__)
+{
+  Elm_Store_Filesystem *st = data;
+  Eina_Iterator *it;
+  const Eina_File_Direct_Info *finf;
+  Eina_List *sorted = NULL;
+  Elm_Store_Item_Info_Filesystem *info;
+
+  // FIXME: need a way to abstract the open, list, feed items from list
+  // and maybe get initial sortable key vals etc.
+  it = eina_file_stat_ls(st->dir);
+  if (!it) return;
+  EINA_ITERATOR_FOREACH(it, finf)
+    {
+      Eina_Bool ok;
+      size_t pathsz = finf->path_length + 1;
+
+      info = calloc(1, sizeof(Elm_Store_Item_Info_Filesystem) + pathsz);
+      if (!info) continue;
+      info->path = ((char *)info) + sizeof(Elm_Store_Item_Info_Filesystem);
+      memcpy(info->path, finf->path, pathsz);
+      ok = EINA_TRUE;
+      if (st->base.cb.list.func)
+        ok = st->base.cb.list.func(st->base.cb.list.data, &info->base);
+      if (ok)
+        {
+          if (!st->base.sorted) ecore_thread_feedback(th, info);
+          else sorted = eina_list_append(sorted, info);
+        }
+      else
+        {
+          if (info->base.sort_id) free(info->base.sort_id);
+          free(info);
+        }
+      if (ecore_thread_check(th)) break;
+    }
+  eina_iterator_free(it);
+  if (sorted)
+    {
+      sorted = eina_list_sort(sorted, 0,
+                              EINA_COMPARE_CB(_store_filesystem_sort_cb));
+      EINA_LIST_FREE(sorted, info)
+        {
+          if (!ecore_thread_check(th)) ecore_thread_feedback(th, info);
+        }
+    }
+}
+//     ************************************************************************
+////   * End of separate thread function.                                     *
+////// ************************************************************************
+
+static void
+_store_filesystem_list_end(void *data, Ecore_Thread *th)
+{
+  Elm_Store *st = data;
+  if (th == st->list_th) st->list_th = NULL;
+}
+
+static void
+_store_filesystem_list_cancel(void *data, Ecore_Thread *th)
+{
+  Elm_Store *st = data;
+  if (th == st->list_th) st->list_th = NULL;
+}
+
+static void
+_store_filesystem_list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
+{
+  Elm_Store *st = data;
+  Elm_Store_Item_Filesystem *sti;
+  Elm_Genlist_Item_Class *itc;
+  Elm_Store_Item_Info_Filesystem *info = msg;
+  
+  sti = calloc(1, sizeof(Elm_Store_Item_Filesystem));
+  if (!sti) goto done;
+  LKI(sti->base.lock);
+  EINA_MAGIC_SET(&(sti->base), ELM_STORE_ITEM_MAGIC);
+  sti->base.store = st;
+  sti->base.data = info->base.data;
+  sti->base.mapping = info->base.mapping;
+  sti->path = eina_stringshare_add(info->path);
+  
+  itc = info->base.item_class;
+  if (!itc) itc = &_store_item_class;
+  else
+    {
+      itc->func.label_get = _store_item_label_get;
+      itc->func.icon_get  = _store_item_icon_get;
+      itc->func.state_get = NULL; // FIXME: support state gets later
+      itc->func.del       = _store_item_del;
+    }
+
+  // FIXME: handle being a parent (tree)
+  sti->base.item = elm_genlist_item_append(st->genlist, itc,
+                                           sti/* item data */,
+                                           NULL/* parent */,
+                                           ELM_GENLIST_ITEM_NONE,
+                                           NULL/* func */,
+                                           NULL/* func data */);
+  st->items = eina_inlist_append(st->items, (Eina_Inlist *)sti);
+done:
+  if (info->base.sort_id) free(info->base.sort_id);
+  free(info);
+}
+
+// public api calls
+static Elm_Store *
+_elm_store_new(size_t size)
+{
+  Elm_Store *st = calloc(1, size);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
+
+  // TODO: BEGIN - move to elm_store_init()
+  eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
+  eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
+  eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
+  // setup default item class (always the same) if list cb doesnt provide one
+  _store_item_class.item_style = "default";
+  _store_item_class.func.label_get = _store_item_label_get;
+  _store_item_class.func.icon_get  = _store_item_icon_get;
+  _store_item_class.func.state_get = NULL; // FIXME: support state gets later
+  _store_item_class.func.del       = _store_item_del;
+  // TODO: END - move to elm_store_init()
+
+  EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
+  st->cache_max = 128;
+  st->fetch_thread = EINA_TRUE;
+  return st;
+}
+#define elm_store_new(type) (type*)_elm_store_new(sizeof(type))
+
+static void
+_elm_store_filesystem_free(Elm_Store *store)
+{
+  Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
+  eina_stringshare_del(st->dir);
+}
+
+static void
+_elm_store_filesystem_item_free(Elm_Store_Item *item)
+{
+   Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
+   eina_stringshare_del(sti->path);
+}
+
+EAPI Elm_Store *
+elm_store_filesystem_new(void)
+{
+  Elm_Store_Filesystem *st = elm_store_new(Elm_Store_Filesystem);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
+
+  EINA_MAGIC_SET(st, ELM_STORE_FILESYSTEM_MAGIC);
+  st->base.free = _elm_store_filesystem_free;
+  st->base.item.free = _elm_store_filesystem_item_free;
+
+  return &st->base;
+}
+
+EAPI void
+elm_store_free(Elm_Store *st)
+{
+  void (*item_free)(Elm_Store_Item *);
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  if (st->list_th)
+    {
+      ecore_thread_cancel(st->list_th);
+      st->list_th = NULL;
+    }
+  eina_list_free(st->realized);
+  item_free = st->item.free;
+  while (st->items)
+    {
+      Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
+      if (sti->eval_job) ecore_job_del(sti->eval_job);
+      if (sti->fetch_th)
+        {
+          ecore_thread_cancel(sti->fetch_th);
+          sti->fetch_th = NULL;
+        }
+      if (item_free) item_free(sti);
+      if (sti->data)
+        {
+          if (st->cb.unfetch.func)
+            st->cb.unfetch.func(st->cb.unfetch.data, sti);
+          sti->data = NULL;
+        }
+      LKD(sti->lock);
+      free(sti);
+    }
+  if (st->genlist)
+    {
+      evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
+      evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
+      evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
+      elm_genlist_clear(st->genlist);
+      st->genlist = NULL;
+    }
+  if (st->free) st->free(st);
+  free(st);
+}
+
+EAPI void
+elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  if (st->genlist == obj) return;
+  if (st->genlist)
+    {
+      evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
+      evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
+      evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
+      elm_genlist_clear(st->genlist);
+    }
+  st->genlist = obj;
+  if (!st->genlist) return;
+  evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
+  evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
+  evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
+  elm_genlist_clear(st->genlist);
+}
+
+EAPI void
+elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
+{
+   Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
+  if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
+  if (store->list_th)
+    {
+      ecore_thread_cancel(store->list_th);
+      store->list_th = NULL;
+    }
+  if (!eina_stringshare_replace(&st->dir, dir)) return;
+  store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
+                                             _store_filesystem_list_update,
+                                             _store_filesystem_list_end,
+                                             _store_filesystem_list_cancel,
+                                             st, EINA_TRUE);
+}
+
+EAPI const char *
+elm_store_filesystem_directory_get(const Elm_Store *store)
+{
+  const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
+  if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
+  return st->dir;
+}
+
+EAPI void
+elm_store_cache_set(Elm_Store *st, int max)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  if (max < 0) max = 0;
+  st->cache_max = max;
+  _store_cache_trim(st);
+}
+
+EAPI int
+elm_store_cache_get(const Elm_Store *st)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
+  return st->cache_max;
+}
+
+EAPI void
+elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  st->cb.list.func = func;
+  st->cb.list.data = (void *)data;
+}
+
+EAPI void
+elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  st->cb.fetch.func = func;
+  st->cb.fetch.data = (void *)data;
+}
+
+EAPI void
+elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  st->fetch_thread = !!use_thread;
+}
+
+EAPI Eina_Bool
+elm_store_fetch_thread_get(const Elm_Store *st)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
+  return st->fetch_thread;
+}
+
+EAPI void
+elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  st->cb.unfetch.func = func;
+  st->cb.unfetch.data = (void *)data;
+}
+
+EAPI void
+elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
+  st->sorted = sorted;
+}
+
+EAPI Eina_Bool
+elm_store_sorted_get(const Elm_Store *st)
+{
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
+  return st->sorted;
+}
+
+EAPI void
+elm_store_item_data_set(Elm_Store_Item *sti, void *data)
+{
+  if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
+  LKL(sti->lock);
+  sti->data = data;
+  LKU(sti->lock);
+}
+
+EAPI void *
+elm_store_item_data_get(Elm_Store_Item *sti)
+{
+  if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
+  void *d;
+  LKL(sti->lock);
+  d = sti->data;
+  LKU(sti->lock);
+  return d;
+}
+
+EAPI const Elm_Store *
+elm_store_item_store_get(const Elm_Store_Item *sti)
+{
+  if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
+  // dont need lock
+  return sti->store;
+}
+
+EAPI const Elm_Genlist_Item *
+elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
+{
+  if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
+  // dont need lock
+  return sti->item;
+}
+
+EAPI const char *
+elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
+{
+  Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
+  Elm_Store_Filesystem *st;
+  if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
+  if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
+  /* ensure we're dealing with filesystem item */
+  st = (Elm_Store_Filesystem *)item->store;
+  if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
+  // dont need lock
+  return sti->path;
+}
diff --git a/src/lib/elm_table.c b/src/lib/elm_table.c
new file mode 100644 (file)
index 0000000..8e296bc
--- /dev/null
@@ -0,0 +1,279 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Table Table
+ *
+ * Arranges widgets in a table where items can also span multiple
+ * columns or rows - even overlap (and then be raised or lowered
+ * accordingly to adjust stacking if they do overlap).
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *tbl;
+};
+
+static const char *widtype = NULL;
+static void _del_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_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_event_callback_del_full
+     (wd->tbl, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+   evas_object_del(wd->tbl);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   free(wd);
+}
+
+static Eina_Bool
+_elm_table_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *items;
+   void *(*list_data_get) (const Eina_List *list);
+   Eina_List *(*list_free) (Eina_List *list);
+
+   if ((!wd) || (!wd->tbl))
+     return EINA_FALSE;
+
+   /* Focus chain */
+   /* TODO: Change this to use other chain */
+   if ((items = elm_widget_focus_custom_chain_get(obj)))
+     {
+        list_data_get = eina_list_data_get;
+        list_free = NULL;
+     }
+   else
+     {
+        items = evas_object_table_children_get(wd->tbl);
+        list_data_get = eina_list_data_get;
+        list_free = eina_list_free;
+
+        if (!items) return EINA_FALSE;
+     }
+
+   Eina_Bool ret = elm_widget_focus_list_next_get(obj, items, list_data_get,
+                                                   dir, next);
+
+   if (list_free)
+     list_free((Eina_List *)items);
+
+   return ret;
+}
+
+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;
+   evas_object_size_hint_min_get(wd->tbl, &minw, &minh);
+   evas_object_size_hint_max_get(wd->tbl, &maxw, &maxh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+   evas_object_geometry_get(obj, 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);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+}
+
+static void
+_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   _sizing_eval(obj);
+}
+
+/**
+ * Add a new table to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Table
+ */
+EAPI Evas_Object *
+elm_table_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "table");
+   elm_widget_type_set(obj, "table");
+   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);
+   elm_widget_focus_next_hook_set(obj, _elm_table_focus_next_hook);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+   elm_widget_highlight_ignore_set(obj, EINA_FALSE);
+
+   wd->tbl = evas_object_table_add(e);
+   evas_object_event_callback_add(wd->tbl, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                 _changed_size_hints, obj);
+   elm_widget_resize_object_set(obj, wd->tbl);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   return obj;
+}
+
+/**
+ * Set the homogenous layout in the table
+ *
+ * @param obj The layout object
+ * @param homogenous A boolean to set (or no) layout homogenous
+ * in the table
+ * (1 = homogenous,  0 = no homogenous)
+ *
+ * @ingroup Table
+ */
+EAPI void
+elm_table_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_table_homogeneous_set(wd->tbl, homogenous);
+}
+
+/**
+ * Get the current table homogenous mode.
+ *
+ * @param obj The table object
+ * @return a boolean to set (or no) layout homogenous in the table
+ * (1 = homogenous,  0 = no homogenous)
+ *
+ * @ingroup Table
+ */
+EAPI Eina_Bool
+elm_table_homogenous_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 evas_object_table_homogeneous_get(wd->tbl);
+}
+
+/**
+ * Set padding between cells.
+ *
+ * @param obj The layout object.
+ * @param horizontal set the horizontal padding.
+ * @param vertical set the vertical padding.
+ *
+ * @ingroup Table
+ */
+EAPI void
+elm_table_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_table_padding_set(wd->tbl, horizontal, vertical);
+}
+
+/**
+ * Get padding between cells.
+ *
+ * @param obj The layout object.
+ * @param horizontal set the horizontal padding.
+ * @param vertical set the vertical padding.
+ *
+ * @ingroup Table
+ */
+EAPI void
+elm_table_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_table_padding_get(wd->tbl, horizontal, vertical);
+}
+
+/**
+ * Add a subobject on the table with the coordinates passed
+ *
+ * @param obj The table object
+ * @param subobj The subobject to be added to the table
+ * @param x Coordinate to X axis
+ * @param y Coordinate to Y axis
+ * @param w Horizontal length
+ * @param h Vertical length
+ *
+ * @ingroup Table
+ */
+EAPI void
+elm_table_pack(Evas_Object *obj, Evas_Object *subobj, int x, int y, int w, int h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_sub_object_add(obj, subobj);
+   evas_object_table_pack(wd->tbl, subobj, x, y, w, h);
+}
+
+/**
+ * Remove child from table.
+ *
+ * @param obj The table object
+ * @param subobj The subobject
+ *
+ * @ingroup Table
+ */
+EAPI void
+elm_table_unpack(Evas_Object *obj, Evas_Object *subobj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_sub_object_del(obj, subobj);
+   evas_object_table_unpack(wd->tbl, subobj);
+}
+
+/**
+ * Faster way to remove all child objects from a table object.
+ *
+ * @param obj The table object
+ * @param clear If true, it will delete just removed children
+ *
+ * @ingroup Table
+ */
+EAPI void
+elm_table_clear(Evas_Object *obj, Eina_Bool clear)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_table_clear(wd->tbl, clear);
+}
diff --git a/src/lib/elm_theme.c b/src/lib/elm_theme.c
new file mode 100644 (file)
index 0000000..19a794b
--- /dev/null
@@ -0,0 +1,866 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Theme
+ *
+ * Functions to modify the theme in the currently running app.
+ */
+
+static Elm_Theme theme_default =
+{
+   NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1
+};
+
+static Eina_List *themes = NULL;
+
+static void
+_elm_theme_clear(Elm_Theme *th)
+{
+   const char *p;
+   EINA_LIST_FREE(th->themes, p)
+      eina_stringshare_del(p);
+   EINA_LIST_FREE(th->overlay, p)
+      eina_stringshare_del(p);
+   EINA_LIST_FREE(th->extension, p)
+      eina_stringshare_del(p);
+   if (th->cache)
+     {
+       eina_hash_free(th->cache);
+       th->cache = NULL;
+     }
+   if (th->theme)
+     {
+        eina_stringshare_del(th->theme);
+        th->theme = NULL;
+     }
+  if (th->ref_theme)
+    {
+      th->ref_theme->referrers = 
+        eina_list_remove(th->ref_theme->referrers, th);
+      elm_theme_free(th->ref_theme);
+      th->ref_theme = NULL;
+    }
+}
+
+static const char *
+_elm_theme_find_try(Elm_Theme *th, const char *f, const char *group)
+{
+   const char *file;
+
+   if (edje_file_group_exists(f, group))
+     {
+       file = eina_stringshare_add(f);
+       if (file)
+         {
+            eina_hash_add(th->cache, group, file);
+            return file;
+         }
+     }
+   return NULL;
+}
+
+static const char *
+_elm_theme_theme_element_try(Elm_Theme *th, const char *home, const char *f, const char *group)
+{
+   char buf[PATH_MAX];
+   const char *file = NULL;
+
+   if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
+       ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
+       ((isalpha(f[0])) && (f[1] == ':')))
+     return _elm_theme_find_try(th, f, group);
+   else if (((f[0] == '~') && (f[1] == '/')))
+     {
+       snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
+       return _elm_theme_find_try(th, buf, group);
+     }
+   snprintf(buf, sizeof(buf), "%s/.elementary/themes/%s.edj", home, f);
+   file = _elm_theme_find_try(th, buf, group);
+   if (file) return file;
+   snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
+   file = _elm_theme_find_try(th, buf, group);
+   return file;
+}
+
+static const char *
+_elm_theme_group_file_find(Elm_Theme *th, const char *group)
+{
+   const Eina_List *l;
+   const char *f;
+   static const char *home = NULL;
+   const char *file = eina_hash_find(th->cache, group);
+
+   if (file) return file;
+   if (!home)
+     {
+       home = getenv("HOME");
+       if (!home) home = "";
+     }
+   EINA_LIST_FOREACH(th->overlay, l, f)
+     {
+       file = _elm_theme_theme_element_try(th, home, f, group);
+       if (file) return file;
+     }
+   EINA_LIST_FOREACH(th->themes, l, f)
+     {
+       file = _elm_theme_theme_element_try(th, home, f, group);
+       if (file) return file;
+     }
+   EINA_LIST_FOREACH(th->extension, l, f)
+     {
+       file = _elm_theme_theme_element_try(th, home, f, group);
+       if (file) return file;
+     }
+   if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group);
+   return NULL;
+}
+
+Eina_Bool
+_elm_theme_object_set(Evas_Object *parent, Evas_Object *o, const char *clas, const char *group, const char *style)
+{
+   Elm_Theme *th = NULL;
+   if (parent) th = elm_widget_theme_get(parent);
+   return _elm_theme_set(th, o, clas, group, style);
+}
+
+Eina_Bool
+_elm_theme_object_icon_set(Evas_Object *parent, Evas_Object *o, const char *group, const char *style)
+{
+   Elm_Theme *th = NULL;
+   if (parent) th = elm_widget_theme_get(parent);
+   return _elm_theme_icon_set(th, o, group, style);
+}
+
+Eina_Bool
+_elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style)
+{
+   const char *file;
+   char buf2[1024];
+   Eina_Bool ok;
+
+   if (!th) th = &(theme_default);
+   snprintf(buf2, sizeof(buf2), "elm/%s/%s/%s", clas, group, style);
+   file = _elm_theme_group_file_find(th, buf2);
+   if (file)
+     {
+       ok = edje_object_file_set(o, file, buf2);
+       if (ok) return EINA_TRUE;
+        else
+          DBG("could not set theme group '%s' from file '%s': %s",
+              buf2, file, edje_load_error_str(edje_object_load_error_get(o)));
+     }
+   snprintf(buf2, sizeof(buf2), "elm/%s/%s/default", clas, group);
+   file = _elm_theme_group_file_find(th, buf2);
+   if (!file) return EINA_FALSE;
+   ok = edje_object_file_set(o, file, buf2);
+   if (!ok)
+     DBG("could not set theme group '%s' from file '%s': %s",
+         buf2, file, edje_load_error_str(edje_object_load_error_get(o)));
+   return ok;
+}
+
+Eina_Bool
+_elm_theme_icon_set(Elm_Theme *th, Evas_Object *o, const char *group, const char *style)
+{
+   const char *file;
+   char buf2[1024];
+   int w, h;
+
+   if (!th) th = &(theme_default);
+   snprintf(buf2, sizeof(buf2), "elm/icon/%s/%s", group, style);
+   file = _elm_theme_group_file_find(th, buf2);
+   if (file)
+     {
+       _els_smart_icon_file_edje_set(o, file, buf2);
+       _els_smart_icon_size_get(o, &w, &h);
+       if (w > 0) return EINA_TRUE;
+     }
+   snprintf(buf2, sizeof(buf2), "elm/icon/%s/default", group);
+   file = _elm_theme_group_file_find(th, buf2);
+   if (!file) return EINA_FALSE;
+   _els_smart_icon_file_edje_set(o, file, buf2);
+   _els_smart_icon_size_get(o, &w, &h);
+   return (w > 0);
+}
+
+Eina_Bool
+_elm_theme_parse(Elm_Theme *th, const char *theme)
+{
+   Eina_List *names = NULL;
+   const char *p, *pe;
+
+   if (!th) th = &(theme_default);
+   if (theme)
+     {
+        p = theme;
+        pe = p;
+        for (;;)
+          {
+             if ((*pe == ':') || (!*pe))
+               { // p -> pe == 'name:'
+                  if (pe > p)
+                    {
+                       char *n = malloc(pe - p + 1);
+                       if (n)
+                         {
+                            const char *nn;
+
+                            strncpy(n, p, pe - p);
+                            n[pe - p] = 0;
+                            nn = eina_stringshare_add(n);
+                            if (nn) names = eina_list_append(names, nn);
+                            free(n);
+                         }
+                    }
+                  if (!*pe) break;
+                  p = pe + 1;
+                  pe = p;
+               }
+             else
+               pe++;
+          }
+     }
+   p = eina_list_data_get(eina_list_last(names));
+   if ((!p) || ((p) && (strcmp(p, "default"))))
+     {
+       p = eina_stringshare_add("default");
+       if (p) names = eina_list_append(names, p);
+     }
+   if (th->cache) eina_hash_free(th->cache);
+   th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
+
+   EINA_LIST_FREE(th->themes, p) eina_stringshare_del(p);
+
+   th->themes = names;
+   return EINA_TRUE;
+}
+
+void
+_elm_theme_shutdown(void)
+{
+   _elm_theme_clear(&(theme_default));
+}
+
+/**
+ * Create a new specific theme
+ * 
+ * This creates an empty specific theme that only uses the default theme. A
+ * specific theme has its own private set of extensions and overlays too
+ * (which are empty by default). Specific themes do not fall back to themes
+ * of parent objects. They are not intended for this use. Use styles, overlays
+ * and extensions when needed, but avoid specific themes unless there is no
+ * other way (example: you want to have a preview of a new theme you are
+ * selecting in a "theme selector" window. The preview is inside a scroller
+ * and should display what the theme you selected will look like, but not
+ * actually apply it yet. The child of the scroller will have a specific
+ * theme set to show this preview before the user decides to apply it to all
+ * applications).
+ * 
+ * @ingroup Theme
+ */
+EAPI Elm_Theme *
+elm_theme_new(void)
+{
+   Elm_Theme *th = calloc(1, sizeof(Elm_Theme));
+   if (!th) return NULL;
+   th->ref = 1;
+   th->themes = eina_list_append(th->themes, eina_stringshare_add("default"));
+   themes = eina_list_append(themes, th);
+   return th;
+}
+
+/**
+ * Free a specific theme
+ * 
+ * @param th The theme to free
+ * 
+ * This frees a theme created with elm_theme_new().
+ * 
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_free(Elm_Theme *th)
+{
+   EINA_SAFETY_ON_NULL_RETURN(th);
+   th->ref--;
+   if (th->ref < 1)
+     {
+        _elm_theme_clear(th);
+        themes = eina_list_remove(themes, th);
+        free(th);
+     }
+}
+
+/**
+ * Copy the theme fom the source to the destination theme
+ * 
+ * @param th The source theme to copy from
+ * @param thdst The destination theme to copy data to
+ * 
+ * This makes a one-time static copy of all the theme config, extensions
+ * and overlays from @p th to @p thdst. If @p th references a theme, then
+ * @p thdst is also set to reference it, with all the theme settings,
+ * overlays and extensions that @p th had.
+ */
+EAPI void
+elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
+{
+   const Eina_List *l;
+   const char *f;
+   
+   if (!th) th = &(theme_default);
+   if (!thdst) thdst = &(theme_default);
+   _elm_theme_clear(thdst);
+   if (th->ref_theme)
+     {
+       thdst->ref_theme = th->ref_theme;
+       thdst->ref_theme->referrers = 
+         eina_list_append(thdst->ref_theme->referrers, thdst);
+       thdst->ref_theme->ref++;
+     }
+   EINA_LIST_FOREACH(th->overlay, l, f)
+     {
+       const char *s = eina_stringshare_add(f);
+       if (s) thdst->overlay = eina_list_append(thdst->overlay, s);
+     }
+   EINA_LIST_FOREACH(th->themes, l, f)
+     {
+       const char *s = eina_stringshare_add(f);
+       if (s) thdst->themes = eina_list_append(thdst->themes, s);
+     }
+   EINA_LIST_FOREACH(th->extension, l, f)
+     {
+       const char *s = eina_stringshare_add(f);
+       if (s) thdst->extension = eina_list_append(thdst->extension, s);
+     }
+   if (th->theme) thdst->theme = eina_stringshare_add(th->theme);
+   elm_theme_flush(thdst);
+}
+
+/**
+ * Tell the source theme to reference the ref theme
+ * 
+ * @param th The theme that will do the referencing
+ * @param thref The theme that is the reference source
+ * 
+ * This clears @p th to be empty and then sets it to refer to @p thref
+ * so @p th acts as an override to @p thdst, but where its overrides
+ * don't apply, it will fall through to @pthref for configuration.
+ */
+EAPI void
+elm_theme_ref_set(Elm_Theme *th, Elm_Theme *thref)
+{
+   if (!th) th = &(theme_default);
+   if (!thref) thref = &(theme_default);
+   if (th->ref_theme == thref) return;
+   _elm_theme_clear(th);
+   if (thref)
+     {
+       thref->referrers = eina_list_append(thref->referrers, th);
+       thref->ref++;
+     }
+   th->ref_theme = thref;
+   elm_theme_flush(th);
+}
+
+/**
+ * Return the theme referred to
+ * 
+ * @param th The theme to get the reference from
+ * @return The referenced theme handle
+ * 
+ * This gets the theme set as the reference theme by elm_theme_ref_set().
+ * If no theme is set as a reference, NULL is returned.
+ */
+EAPI Elm_Theme *
+elm_theme_ref_get(Elm_Theme *th)
+{
+   if (!th) th = &(theme_default);
+   return th->ref_theme;
+}
+
+/**
+ * Return the default theme
+ * 
+ * @return The default theme handle
+ * 
+ * This returns the internal default theme setup handle that all widgets
+ * use implicitly unless a specific theme is set. This is also often use
+ * as a shorthand of NULL.
+ */
+EAPI Elm_Theme *
+elm_theme_default_get(void)
+{
+   return &theme_default;
+}
+
+/**
+ * Prepends a theme overlay to the list of overlays
+ *
+ * @param th The theme to add to, or if NULL, the default theme
+ * @param item The Edje file path to be used
+ * 
+ * Use this if your application needs to provide some custom overlay theme
+ * (An Edje file that replaces some default styles of widgets) where adding
+ * new styles, or changing system theme configuration is not possible. Do
+ * NOT use this instead of a proper system theme configuration. Use proper
+ * configuration files, profiles, environment variables etc. to set a theme
+ * so that the theme can be altered by simple confiugration by a user. Using
+ * this call to achieve that effect is abusing the API and will create lots
+ * of trouble.
+ *
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_overlay_add(Elm_Theme *th, const char *item)
+{
+   const char *f = eina_stringshare_add(item);
+
+   if (!th) th = &(theme_default);
+   if (f) th->overlay = eina_list_prepend(th->overlay, f);
+   elm_theme_flush(th);
+}
+
+/**
+ * Delete a theme overlay from the list of overlays
+ *
+ * @param th The theme to delete from, or if NULL, the default theme
+ * @param item The name of the theme overlay
+ *
+ * See elm_theme_overlay_add().
+ * 
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_overlay_del(Elm_Theme *th, const char *item)
+{
+   const Eina_List *l;
+   const char *f, *s;
+
+   if (!th) th = &(theme_default);
+   s = eina_stringshare_add(item);
+   EINA_LIST_FOREACH(th->overlay, l, f)
+     if (f == s)
+       {
+         eina_stringshare_del(f);
+         th->overlay = eina_list_remove_list(th->overlay, (Eina_List *)l);
+         break;
+       }
+   eina_stringshare_del(s);
+   elm_theme_flush(th);
+}
+
+/**
+ * Appends a theme extension to the list of extensions.
+ *
+ * @param th The theme to add to, or if NULL, the default theme
+ * @param item The Edje file path to be used
+ *
+ * This is intended when an application needs more styles of widgets or new
+ * widget themes that the default does not provide (or may not provide). The
+ * application has "extended" usage by coming up with new custom style names
+ * for widgets for specific uses, but as these are not "standard", they are
+ * not guaranteed to be provided by a default theme. This means the
+ * application is required to provide these extra elements itself in specific
+ * Edje files. This call adds one of those Edje files to the theme search
+ * path to be search after the default theme. The use of this call is
+ * encouraged when default styles do not meet the needs of the application.
+ * Use this call instead of elm_theme_overlay_add() for almost all cases.
+ * 
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_extension_add(Elm_Theme *th, const char *item)
+{
+   const char *f = eina_stringshare_add(item);
+
+   if (!th) th = &(theme_default);
+   if (f) th->extension = eina_list_append(th->extension, f);
+   elm_theme_flush(th);
+}
+
+/**
+ * Deletes a theme extension from the list of extensions.
+ *
+ * @param th The theme to delete from, or if NULL, the default theme
+ * @param item The name of the theme extension
+ * 
+ * See elm_theme_extension_add().
+ *
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_extension_del(Elm_Theme *th, const char *item)
+{
+   const Eina_List *l;
+   const char *f, *s;
+
+   if (!th) th = &(theme_default);
+   s = eina_stringshare_add(item);
+   EINA_LIST_FOREACH(th->extension, l, f)
+     if (f == s)
+       {
+         eina_stringshare_del(f);
+         th->extension = eina_list_remove_list(th->extension, (Eina_List *)l);
+         break;
+       }
+   eina_stringshare_del(s);
+   elm_theme_flush(th);
+}
+
+/**
+ * Set the theme search order for the given theme
+ * 
+ * @param th The theme to set the search order, or if NULL, the default theme
+ * @param theme Theme search string
+ * 
+ * This sets the search string for the theme in path-notation from first
+ * theme to search, to last, delimited by the : character. Example:
+ * 
+ * "shiny:/path/to/file.edj:default"
+ * 
+ * See the ELM_THEME environment variable for more information.
+ * 
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_set(Elm_Theme *th, const char *theme)
+{
+   if (!th) th = &(theme_default);
+   _elm_theme_parse(th, theme);
+   if (th->theme)
+     {
+        eina_stringshare_del(th->theme);
+        th->theme = NULL;
+     }
+   elm_theme_flush(th);
+}
+
+/**
+ * Return the theme search order
+ * 
+ * @param th The theme to get the search order, or if NULL, the default theme
+ * @return The internal search order path
+ * 
+ * See elm_theme_set() for more information.
+ * 
+ * @ingroup Theme
+ */
+EAPI const char *
+elm_theme_get(Elm_Theme *th)
+{
+   if (!th) th = &(theme_default);
+   if (!th->theme)
+     {
+        Eina_List *l;
+        const char *f;
+        char *tmp;
+        int len;
+
+        len = 0;
+        EINA_LIST_FOREACH(th->themes, l, f)
+          {
+             len += strlen(f);
+             if (l->next) len += 1;
+          }
+        tmp = alloca(len + 1);
+        tmp[0] = 0;
+        EINA_LIST_FOREACH(th->themes, l, f)
+          {
+             strcat(tmp, f);
+             if (l->next) strcat(tmp, ":");
+          }
+        th->theme = eina_stringshare_add(tmp);
+     }
+   return th->theme;
+}
+
+/**
+ * Return a list of theme elements to be used in a theme.
+ * 
+ * @param th Theme to get the list of theme elements from.
+ * @return The internal list of theme elements
+ * 
+ * This returns the internal list of theme elements (will only be valid as
+ * long as the theme is not modified by elm_theme_set() or theme is not
+ * freed by elm_theme_free(). This is a list of strings which must not be
+ * altered as they are also internal. If @p th is NULL, then the default
+ * theme element list is returned.
+ */
+EAPI const Eina_List *
+elm_theme_list_get(const Elm_Theme *th)
+{
+   if (!th) th = &(theme_default);
+   return th->themes;
+}
+
+/**
+ * Return the full patrh for a theme element
+ * 
+ * @param f The theme element name
+ * @param in_search_path Pointer to a boolean to indicate if item is in the search path or not
+ * @return The full path to the file found.
+ * 
+ * This returns a string you should free with free() on success, NULL on
+ * failure. This will search for the given theme element, and if it is a
+ * full or relative path element or a simple searchable name. The returned
+ * path is the full path to the file, if searched, and the file exists, or it
+ * is simply the full path given in the element or a resolved path if
+ * relative to home. The @p in_search_path boolean pointed to is set to
+ * EINA_TRUE if the file was a searchable file andis in the search path,
+ * and EINA_FALSE otherwise.
+ */
+EAPI char *
+elm_theme_list_item_path_get(const char *f, Eina_Bool *in_search_path)
+{
+   static const char *home = NULL;
+   char buf[PATH_MAX];
+   
+   if (!f)
+     {
+        if (in_search_path) *in_search_path = EINA_FALSE;
+        return NULL;
+     }
+   
+   if (!home)
+     {
+       home = getenv("HOME");
+       if (!home) home = "";
+     }
+   
+   if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
+       ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
+       ((isalpha(f[0])) && (f[1] == ':')))
+     {
+        if (in_search_path) *in_search_path = EINA_FALSE;
+        return strdup(f);
+     }
+   else if (((f[0] == '~') && (f[1] == '/')))
+     {
+        if (in_search_path) *in_search_path = EINA_FALSE;
+       snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
+        return strdup(buf);
+     }
+   snprintf(buf, sizeof(buf), "%s/.elementary/themes/%s.edj", home, f);
+   if (ecore_file_exists(buf))
+     {
+        if (in_search_path) *in_search_path = EINA_TRUE;
+        return strdup(buf);
+     }
+   
+   snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
+   if (ecore_file_exists(buf))
+     {
+        if (in_search_path) *in_search_path = EINA_TRUE;
+        return strdup(buf);
+     }
+   
+   if (in_search_path) *in_search_path = EINA_FALSE;
+   return NULL;
+}
+
+/**
+ * Flush the current theme.
+ * 
+ * @param th Theme to flush
+ * 
+ * This flushes caches that let elementary know where to find theme elements
+ * in the given theme. If @p th is NULL, then the default theme is flushed.
+ * Call this call if source theme data has changed in such a way as to
+ * make any caches Elementary kept invalid.
+ *
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_flush(Elm_Theme *th)
+{
+   if (!th) th = &(theme_default);
+   if (th->cache) eina_hash_free(th->cache);
+   th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
+   _elm_win_rescale(th, EINA_TRUE);
+   if (th->referrers)
+     {
+        Eina_List *l;
+        Elm_Theme *th2;
+
+        EINA_LIST_FOREACH(th->referrers, l, th2) elm_theme_flush(th2);
+     }
+}
+
+/**
+ * This flushes all themes (default and specific ones).
+ * 
+ * This will flush all themes in the current application context, by calling
+ * elm_theme_flush() on each of them.
+ * 
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_full_flush(void)
+{
+   Eina_List *l;
+   Elm_Theme *th;
+   
+   EINA_LIST_FOREACH(themes, l, th)
+     {
+        elm_theme_flush(th);
+     }
+   elm_theme_flush(&(theme_default));
+}
+
+/**
+ * Set the theme for all elementary using applications on the current display
+ *
+ * @param theme The name of the theme to use. Format same as the ELM_THEME
+ * environment variable.
+ *
+ * @ingroup Theme
+ */
+EAPI void
+elm_theme_all_set(const char *theme)
+{
+#ifdef HAVE_ELEMENTARY_X
+   static Ecore_X_Atom atom = 0;
+   
+   if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_THEME");
+   ecore_x_window_prop_string_set(ecore_x_window_root_first_get(),
+                                  atom, theme);
+#endif
+   elm_theme_set(NULL, theme);
+}
+
+/**
+ * Return a list of theme elements in the theme search path
+ * 
+ * @return A list of strings that are the theme element names.
+ * 
+ * This lists all available theme files in the standard Elementary search path
+ * for theme elements, and returns them in alphabetical order as theme
+ * element names in a list of strings. Free this with 
+ * elm_theme_name_available_list_free() when you are done with the list.
+ */
+EAPI Eina_List *
+elm_theme_name_available_list_new(void)
+{
+   Eina_List *list = NULL;
+   Eina_List *dir, *l;
+   char buf[PATH_MAX], *file, *s, *th;
+   static const char *home = NULL;
+   
+   if (!home)
+     {
+        home = getenv("HOME");
+        if (!home) home = "";
+     }
+   
+   snprintf(buf, sizeof(buf), "%s/.elementary/themes", home);
+   dir = ecore_file_ls(buf);
+   EINA_LIST_FREE(dir, file)
+     {
+        snprintf(buf, sizeof(buf), "%s/.elementary/themes/%s", home, file);
+        if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
+          {
+             s = strchr(file, '.');
+             if ((s) && (!strcasecmp(s, ".edj")))
+               {
+                  th = strdup(file);
+                  s = strchr(th, '.');
+                  *s = 0;
+                  list = eina_list_append(list, th);
+               }
+          }
+        free(file);
+     }
+
+   snprintf(buf, sizeof(buf), "%s/themes", _elm_data_dir);
+   dir = ecore_file_ls(buf);
+   EINA_LIST_FREE(dir, file)
+     {
+        snprintf(buf, sizeof(buf), "%s/themes/%s", _elm_data_dir, file);
+        if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
+          {
+             s = strchr(file, '.');
+             if ((s) && (!strcasecmp(s, ".edj")))
+               {
+                  int dup;
+                  
+                  th = strdup(file);
+                  s = strchr(th, '.');
+                  *s = 0;
+                  dup = 0;
+                  EINA_LIST_FOREACH(list, l, s)
+                    {
+                       if (!strcmp(s, th))
+                         {
+                            dup = 1;
+                            break;
+                         }
+                    }
+                  if (dup) free(th);
+                  else list = eina_list_append(list, th);
+               }
+          }
+        free(file);
+     }
+   list = eina_list_sort(list, 0, EINA_COMPARE_CB(strcasecmp));
+   return list;
+}
+
+/**
+ * Free the list returned by elm_theme_name_available_list_new()
+ * 
+ * This frees the list of themes returned by 
+ * elm_theme_name_available_list_new(). Once freed the list should no longer
+ * be used. a new list mys be created.
+ */
+EAPI void
+elm_theme_name_available_list_free(Eina_List *list)
+{
+   char *s;
+   EINA_LIST_FREE(list, s) free(s);
+}
+
+/**
+ * Set a specific theme to be used for this object and its children
+ * 
+ * @param obj The object to set the theme on
+ * @param th The theme to set
+ * 
+ * This sets a specific theme that will be used for the given object and any
+ * child objects it has. If @p th is NULL then the theme to be used is
+ * cleared and the object will inherit its theme from its parent (which
+ * ultimately will use the default theme if no specific themes are set).
+ * 
+ * Use special themes with great care as this will annoy users and make
+ * configuration difficult. Avoid any custom themes at all if it can be
+ * helped.
+ * 
+ * @ingroup Theme
+ */
+EAPI void
+elm_object_theme_set(Evas_Object *obj, Elm_Theme *th)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_theme_set(obj, th);
+}
+
+/**
+ * Get the specific theme to be used
+ * 
+ * @param obj The object to get the specific theme from
+ * @return The specifc theme set.
+ * 
+ * This will return a specific theme set, or NULL if no specific theme is
+ * set on that object. It will not return inherited themes from parents, only
+ * the specific theme set for that specific object. See elm_object_theme_set()
+ * for more information.
+ * 
+ * @ingroup Theme
+ */
+EAPI Elm_Theme *
+elm_object_theme_get(const Evas_Object *obj)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   return elm_widget_theme_get(obj);
+}
diff --git a/src/lib/elm_thumb.c b/src/lib/elm_thumb.c
new file mode 100644 (file)
index 0000000..ecda646
--- /dev/null
@@ -0,0 +1,755 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Thumb Thumb
+ *
+ * A thumb object is used for displaying the thumbnail of an image or video.
+ * You must have compiled Elementary with Ethumb_Client support and the DBus
+ * service must be present and auto-activated in order to have thumbnails to
+ * be generated.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * clicked - This is called when a user has clicked the thumb without dragging
+ * around.
+ *
+ * clicked,double - This is called when a user has double-clicked the thumb.
+ *
+ * press - This is called when a user has pressed down the thumb.
+ *
+ * generate,start - The thumbnail generation started.
+ *
+ * generate,stop - The generation process stopped.
+ *
+ * generate,error - The generation failed.
+ *
+ * load,error - The thumbnail image loading failed.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *self;
+   Evas_Object *frame;
+   Evas_Object *view;
+   const char *file;
+   const char *key;
+   struct
+     {
+       int id;
+       const char *file;
+       const char *key;
+     } thumb;
+   Ecore_Event_Handler *eeh;
+   Elm_Thumb_Animation_Setting anim_setting;
+   Eina_Bool on_hold : 1;
+   Eina_Bool is_video : 1;
+   Eina_Bool was_video : 1;
+   Eina_Bool edit : 1;
+};
+
+static const char *widtype = NULL;
+
+#define SIG_CLICKED "clicked"
+#define SIG_CLICKED_DOUBLE "clicked,double"
+#define SIG_GENERATE_ERROR "generate,error"
+#define SIG_GENERATE_START "generate,start"
+#define SIG_GENERATE_STOP "generate,stop"
+#define SIG_LOAD_ERROR "load,error"
+#define SIG_PRESS "press"
+
+static const Evas_Smart_Cb_Description _signals[] = 
+{
+  {SIG_CLICKED, ""},
+  {SIG_CLICKED_DOUBLE, ""},
+  {SIG_GENERATE_ERROR, ""},
+  {SIG_GENERATE_START, ""},
+  {SIG_GENERATE_STOP, ""},
+  {SIG_LOAD_ERROR, ""},
+  {SIG_PRESS, ""},
+  {NULL, NULL}
+};
+
+#define EDJE_SIGNAL_GENERATE_START "elm,thumb,generate,start"
+#define EDJE_SIGNAL_GENERATE_STOP "elm,thumb,generate,stop"
+#define EDJE_SIGNAL_GENERATE_ERROR "elm,thumb,generate,error"
+#define EDJE_SIGNAL_LOAD_ERROR "elm,thumb,load,error"
+#define EDJE_SIGNAL_PULSE_START "elm,state,pulse,start"
+#define EDJE_SIGNAL_PULSE_STOP "elm,state,pulse,stop"
+
+struct _Ethumb_Client *_elm_ethumb_client = NULL;
+Eina_Bool _elm_ethumb_connected = EINA_FALSE;
+
+EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+#ifdef HAVE_ELEMENTARY_ETHUMB
+   if (wd->thumb.id >= 0)
+     ethumb_client_generate_cancel(_elm_ethumb_client, wd->thumb.id,
+                                   NULL, NULL, NULL);
+#endif
+
+   eina_stringshare_del(wd->file);
+   eina_stringshare_del(wd->key);
+   if (wd->eeh) ecore_event_handler_del(wd->eeh);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   _elm_theme_object_set(obj, wd->frame, "thumb", "base", 
+                         elm_widget_style_get(obj));
+}
+
+#ifdef HAVE_ELEMENTARY_ETHUMB
+static void
+_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = data;
+   Evas_Event_Mouse_Down *ev = event_info;
+
+   if (ev->button != 1)
+     return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     wd->on_hold = EINA_TRUE;
+   else
+     wd->on_hold = EINA_FALSE;
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     evas_object_smart_callback_call(wd->self, SIG_CLICKED_DOUBLE, NULL);
+   else
+     evas_object_smart_callback_call(wd->self, SIG_PRESS, NULL);
+}
+
+static void
+_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Widget_Data *wd = data;
+   Evas_Event_Mouse_Up *ev = event_info;
+
+   if (ev->button != 1)
+     return;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     wd->on_hold = EINA_TRUE;
+   else
+     wd->on_hold = EINA_FALSE;
+   if (!wd->on_hold)
+     evas_object_smart_callback_call(wd->self, SIG_CLICKED, NULL);
+   wd->on_hold = EINA_FALSE;
+}
+
+static void
+_finished_thumb(Widget_Data *wd, const char *thumb_path, const char *thumb_key)
+{
+   Eina_Bool new_view = EINA_FALSE;
+   int r;
+   Evas_Coord mw, mh;
+   Evas *evas;
+
+   evas = evas_object_evas_get(wd->self);
+   if ((wd->view) && (wd->is_video ^ wd->was_video))
+     {
+       evas_object_del(wd->view);
+       wd->view = NULL;
+     }
+   wd->was_video = wd->is_video;
+
+   if ((wd->is_video) &&
+       (ethumb_client_format_get(_elm_ethumb_client) == ETHUMB_THUMB_EET))
+     {
+       if (!wd->view)
+         {
+            wd->view = edje_object_add(evas);
+            if (!wd->view)
+              {
+                 ERR("could not create edje object");
+                 goto err;
+              }
+            new_view = EINA_TRUE;
+         }
+
+       if (!edje_object_file_set(wd->view, thumb_path, "movie/thumb"))
+         {
+            ERR("could not set file=%s key=%s for %s", thumb_path, thumb_key,
+                wd->file);
+            goto view_err;
+         }
+     }
+   else
+     {
+       if (!wd->view)
+         {
+            wd->view = evas_object_image_filled_add(evas);
+            if (!wd->view)
+              {
+                 ERR("could not create image object");
+                 goto err;
+              }
+            new_view = EINA_TRUE;
+         }
+
+       evas_object_image_file_set(wd->view, thumb_path, thumb_key);
+       r = evas_object_image_load_error_get(wd->view);
+       if (r != EVAS_LOAD_ERROR_NONE)
+         {
+            ERR("%s: %s", thumb_path, evas_load_error_str(r));
+            goto view_err;
+         }
+     }
+
+   if (new_view) elm_widget_sub_object_add(wd->self, wd->view);
+   edje_object_part_swallow(wd->frame, "elm.swallow.content", wd->view);
+   edje_object_size_min_get(wd->frame, &mw, &mh);
+   edje_object_size_min_restricted_calc(wd->frame, &mw, &mh, mw, mh);
+   evas_object_size_hint_min_set(wd->self, mw, mh);
+   eina_stringshare_replace(&(wd->thumb.file), thumb_path);
+   eina_stringshare_replace(&(wd->thumb.key), thumb_key);
+   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
+   evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
+   return;
+
+view_err:
+   evas_object_del(wd->view);
+   wd->view = NULL;
+err:
+   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm");
+   evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL);
+}
+
+static void
+_finished_thumb_cb(void *data, Ethumb_Client *c __UNUSED__, int id, const char *file, const char *key, const char *thumb_path, const char *thumb_key, Eina_Bool success)
+{
+   Widget_Data *wd = data;
+
+   EINA_SAFETY_ON_FALSE_RETURN(wd->thumb.id == id);
+   wd->thumb.id = -1;
+
+   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_STOP, "elm");
+
+   if (success)
+     {
+       _finished_thumb(wd, thumb_path, thumb_key);
+       return;
+     }
+
+   ERR("could not generate thumbnail for %s (key: %s)", file, key ? key : "");
+   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm");
+   evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
+}
+
+static void
+_thumb_apply(Widget_Data *wd)
+{
+   if (wd->thumb.id > 0)
+     {
+        ethumb_client_generate_cancel
+          (_elm_ethumb_client, wd->thumb.id, NULL, NULL, NULL);
+        wd->thumb.id = -1;
+     }
+
+   if (!wd->file) return;
+
+   ethumb_client_file_set(_elm_ethumb_client, wd->file, wd->key);
+   if (ethumb_client_thumb_exists(_elm_ethumb_client))
+     {
+       const char *thumb_path, *thumb_key;
+
+       wd->thumb.id = -1;
+       ethumb_client_thumb_path_get(_elm_ethumb_client, &thumb_path,
+                                    &thumb_key);
+       _finished_thumb(wd, thumb_path, thumb_key);
+       return;
+     }
+   else if ((wd->thumb.id = ethumb_client_generate
+            (_elm_ethumb_client, _finished_thumb_cb, wd, NULL)) != -1)
+     {
+       edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_START, "elm");
+       edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_START, "elm");
+       evas_object_smart_callback_call(wd->self, SIG_GENERATE_START, NULL);
+     }
+   else
+     {
+       wd->thumb.id = -1;
+       edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm");
+       evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
+     }
+}
+
+static Eina_Bool
+_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
+{
+   _thumb_apply(data);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_thumb_show(Widget_Data *wd)
+{
+   evas_object_show(wd->frame);
+
+   if (elm_thumb_ethumb_client_connected())
+     {
+       _thumb_apply(wd);
+       return;
+     }
+
+   if (!wd->eeh)
+     wd->eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT,
+                                      _thumb_apply_cb, wd);
+}
+
+static void
+_thumb_show_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _thumb_show(data);
+}
+
+static void
+_thumb_hide_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = data;
+
+   evas_object_hide(wd->frame);
+
+   if (wd->thumb.id >= 0)
+     {
+       ethumb_client_generate_cancel
+         (_elm_ethumb_client, wd->thumb.id, NULL, NULL, NULL);
+       wd->thumb.id = -1;
+
+       edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
+       evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
+     }
+
+   if (wd->eeh)
+     {
+       ecore_event_handler_del(wd->eeh);
+       wd->eeh = NULL;
+     }
+}
+
+#endif
+
+#ifdef ELM_ETHUMB
+static int _elm_need_ethumb = 0;
+
+static void _on_die_cb(void *, Ethumb_Client *);
+
+static void
+_connect_cb(void *data __UNUSED__, Ethumb_Client *c, Eina_Bool success)
+{
+   if (success)
+     {
+       ethumb_client_on_server_die_callback_set(c, _on_die_cb, NULL, NULL);
+       _elm_ethumb_connected = EINA_TRUE;
+       ecore_event_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, NULL, NULL, NULL);
+     }
+   else
+     _elm_ethumb_client = NULL;
+}
+
+static void
+_on_die_cb(void *data __UNUSED__, Ethumb_Client *c __UNUSED__)
+{
+   ethumb_client_disconnect(_elm_ethumb_client);
+   _elm_ethumb_client = NULL;
+   _elm_ethumb_connected = EINA_FALSE;
+   _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
+}
+#endif
+
+void
+_elm_unneed_ethumb(void)
+{
+#ifdef ELM_ETHUMB
+   if (--_elm_need_ethumb) return;
+
+   ethumb_client_disconnect(_elm_ethumb_client);
+   _elm_ethumb_client = NULL;
+   ethumb_client_shutdown();
+   ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
+#endif
+}
+
+static Eina_Bool
+_elm_thumb_dropcb(void *data __UNUSED__, Evas_Object *o, Elm_Selection_Data *drop)
+{
+   if ((!o) || (!drop) || (!drop->data)) return EINA_FALSE;
+   elm_thumb_file_set(o, drop->data, NULL);
+   return EINA_TRUE;
+}
+
+/**
+ * This must be called before any other function that handle with
+ * elm_thumb objects or ethumb_client instances.
+ *
+ * @ingroup Thumb
+ */
+EAPI Eina_Bool
+elm_need_ethumb(void)
+{
+#ifdef ELM_ETHUMB
+   if (_elm_need_ethumb++) return EINA_TRUE;
+   ELM_ECORE_EVENT_ETHUMB_CONNECT = ecore_event_type_new();
+   ethumb_client_init();
+   _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
+   return EINA_TRUE;
+#else
+   return EINA_FALSE;
+#endif
+}
+
+/**
+ * Add a new thumb object to the parent.
+ *
+ * @param parent The parent object.
+ * @return The new object or NULL if it cannot be created.
+ *
+ * @see elm_thumb_file_set()
+ * @see elm_thumb_ethumb_client_get()
+ *
+ * @ingroup Thumb
+ */
+EAPI Evas_Object *
+elm_thumb_add(Evas_Object *parent)
+{
+   Evas *evas;
+   Widget_Data *wd;
+   Evas_Object *obj;
+   Evas_Coord minw, minh;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   evas = evas_object_evas_get(parent);
+   if (!evas) return NULL;
+   obj = elm_widget_add(evas);
+   ELM_SET_WIDTYPE(widtype, "thumb");
+   elm_widget_type_set(obj, "thumb");
+   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, EINA_FALSE);
+
+   wd->frame = edje_object_add(evas);
+   _elm_theme_object_set(obj, wd->frame, "thumb", "base", "default");
+   elm_widget_resize_object_set(obj, wd->frame);
+
+   edje_object_size_min_calc(obj, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+
+   wd->self = obj;
+   wd->view = NULL;
+   wd->file = NULL;
+   wd->key = NULL;
+   wd->eeh = NULL;
+   wd->thumb.id = -1;
+   wd->on_hold = EINA_FALSE;
+   wd->is_video = EINA_FALSE;
+   wd->was_video = EINA_FALSE;
+
+#ifdef HAVE_ELEMENTARY_ETHUMB
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                 _mouse_down_cb, wd);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
+                                 _mouse_up_cb, wd);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW,
+                                 _thumb_show_cb, wd);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
+                                 _thumb_hide_cb, wd);
+#endif
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Reload thumbnail if it was generated before.
+ *
+ * This is useful if the ethumb client configuration changed, like its
+ * size, aspect or any other property one set in the handle returned
+ * by elm_thumb_ethumb_client_get().
+ *
+ * @param obj The thumb object to reload
+ *
+ * @see elm_thumb_file_set()
+ *
+ * @ingroup Thumb
+ */
+EAPI void
+elm_thumb_reload(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   eina_stringshare_replace(&(wd->thumb.file), NULL);
+   eina_stringshare_replace(&(wd->thumb.key), NULL);
+
+#ifdef HAVE_ELEMENTARY_ETHUMB
+   if (evas_object_visible_get(obj))
+     _thumb_show(wd);
+#endif
+}
+
+/**
+ * Set the file that will be used as thumbnail.
+ *
+ * The file can be an image or a video (in that case, acceptable extensions are:
+ * avi, mp4, ogv, mov, mpg and wmv). To start the video animation, use the
+ * function elm_thumb_animate().
+ *
+ * @param obj The thumb object.
+ * @param file The path to file that will be used as thumb.
+ * @param key The key used in case of an EET file.
+ *
+ * @see elm_thumb_file_get()
+ * @see elm_thumb_reload()
+ * @see elm_thumb_animate()
+ *
+ * @ingroup Thumb
+ */
+EAPI void
+elm_thumb_file_set(Evas_Object *obj, const char *file, const char *key)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Eina_Bool file_replaced, key_replaced;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   file_replaced = eina_stringshare_replace(&(wd->file), file);
+   key_replaced = eina_stringshare_replace(&(wd->key), key);
+
+   if (file_replaced)
+     {
+       int prefix_size;
+       const char **ext, *ptr;
+       static const char *extensions[] = 
+          {
+             ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
+          };
+
+       prefix_size = eina_stringshare_strlen(wd->file) - 4;
+       if (prefix_size >= 0)
+         {
+            ptr = wd->file + prefix_size;
+            wd->is_video = EINA_FALSE;
+            for (ext = extensions; *ext; ext++)
+              if (!strcasecmp(ptr, *ext))
+                {
+                   wd->is_video = EINA_TRUE;
+                   break;
+                }
+         }
+     }
+
+   eina_stringshare_replace(&(wd->thumb.file), NULL);
+   eina_stringshare_replace(&(wd->thumb.key), NULL);
+
+#ifdef HAVE_ELEMENTARY_ETHUMB
+   if (((file_replaced) || (key_replaced)) && (evas_object_visible_get(obj)))
+     _thumb_show(wd);
+#endif
+}
+
+/**
+ * Get the image or video path and key used to generate the thumbnail.
+ *
+ * @param obj The thumb object.
+ * @param file Pointer to filename.
+ * @param key Pointer to key.
+ *
+ * @see elm_thumb_file_set()
+ * @see elm_thumb_path_get()
+ * @see elm_thumb_animate()
+ *
+ * @ingroup Thumb
+ */
+EAPI void
+elm_thumb_file_get(const Evas_Object *obj, const char **file, const char **key)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (file)
+     *file = wd->file;
+   if (key)
+     *key = wd->key;
+}
+
+/**
+ * Get the path and key to the image or video generated by ethumb.
+ *
+ * One just need to make sure that the thumbnail was generated before getting
+ * its path; otherwise, the path will be NULL. One way to do that is by asking
+ * for the path when/after the "generate,stop" smart callback is called.
+ *
+ * @param obj The thumb object.
+ * @param file Pointer to thumb path.
+ * @param key Pointer to thumb key.
+ *
+ * @see elm_thumb_file_get()
+ *
+ * @ingroup Thumb
+ */
+EAPI void
+elm_thumb_path_get(const Evas_Object *obj, const char **file, const char **key)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (file)
+     *file = wd->thumb.file;
+   if (key)
+     *key = wd->thumb.key;
+}
+
+/**
+ * Set the animation state for the thumb object. If its content is an animated
+ * video, you may start/stop the animation or tell it to play continuously and
+ * looping.
+ *
+ * @param obj The thumb object.
+ * @param setting The animation setting.
+ *
+ * @see elm_thumb_file_set()
+ *
+ * @ingroup Thumb
+ */
+EAPI void
+elm_thumb_animate_set(Evas_Object *obj, Elm_Thumb_Animation_Setting setting)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   EINA_SAFETY_ON_TRUE_RETURN(setting >= ELM_THUMB_ANIMATION_LAST);
+
+   wd->anim_setting = setting;
+   if (setting == ELM_THUMB_ANIMATION_LOOP)
+     edje_object_signal_emit(wd->view, "animate_loop", "");
+   else if (setting == ELM_THUMB_ANIMATION_START)
+     edje_object_signal_emit(wd->view, "animate", "");
+   else if (setting == ELM_THUMB_ANIMATION_STOP)
+     edje_object_signal_emit(wd->view, "animate_stop", "");
+}
+
+/**
+ * Get the animation state for the thumb object.
+ *
+ * @param obj The thumb object.
+ * @return getting The animation setting or @c ELM_THUMB_ANIMATION_LAST,
+ * on errors.
+ *
+ * @see elm_thumb_file_get()
+ *
+ * @ingroup Thumb
+ */
+EAPI Elm_Thumb_Animation_Setting
+elm_thumb_animate_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_THUMB_ANIMATION_LAST;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   return wd->anim_setting;
+}
+
+/**
+ * Get the ethumb_client handle so custom configuration can be made.
+ * This must be called before the objects are created to be sure no object is
+ * visible and no generation started.
+ *
+ * @return Ethumb_Client instance or NULL.
+ *
+ * Example of usage:
+ *
+ * @code
+ * #include <Elementary.h>
+ * #ifndef ELM_LIB_QUICKLAUNCH
+ * EAPI int
+ * elm_main(int argc, char **argv)
+ * {
+ *    Ethumb_Client *client;
+ *
+ *    elm_need_ethumb();
+ *
+ *    // ... your code
+ *
+ *    client = elm_thumb_ethumb_client_get();
+ *    if (!client)
+ *      {
+ *         ERR("could not get ethumb_client");
+ *         return 1;
+ *      }
+ *    ethumb_client_size_set(client, 100, 100);
+ *    ethumb_client_crop_align_set(client, 0.5, 0.5);
+ *    // ... your code
+ *
+ *    // Create elm_thumb objects here
+ *
+ *    elm_run();
+ *    elm_shutdown();
+ *    return 0;
+ * }
+ * #endif
+ * ELM_MAIN()
+ * @endcode
+ *
+ * @ingroup Thumb
+ */
+EAPI void *
+elm_thumb_ethumb_client_get(void)
+{
+   return _elm_ethumb_client;
+}
+
+/**
+ * Get the ethumb_client connection state.
+ *
+ * @return EINA_TRUE if the client is connected to the server or
+ *        EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool
+elm_thumb_ethumb_client_connected(void)
+{
+   return _elm_ethumb_connected;
+}
+
+EAPI Eina_Bool
+elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return EINA_FALSE;
+   edit = !!edit;
+   if (wd->edit == edit) return EINA_TRUE;
+
+   wd->edit = edit;
+   if (wd->edit)
+      elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE,
+                            _elm_thumb_dropcb, obj);
+   else
+      elm_drop_target_del(obj);
+
+   return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+elm_thumb_editable_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->edit;
+}
+
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/src/lib/elm_toggle.c b/src/lib/elm_toggle.c
new file mode 100644 (file)
index 0000000..bfd2857
--- /dev/null
@@ -0,0 +1,480 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Toggle
+ *
+ * A toggle is a slider which can be used to toggle between
+ * two values.  It has two states: on and off.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * changed - Whenever the toggle value has been changed.  Is not called
+ * until the toggle is released by the cursor (assuming it has been triggered
+ * by the cursor in the first place).
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *tgl;
+   Evas_Object *icon;
+   Eina_Bool state;
+   Eina_Bool *statep;
+   const char *label;
+   const char *ontext, *offtext;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _disable_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 _signal_toggle_off(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_toggle_on(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
+                             Evas_Callback_Type type, void *event_info);
+
+static const char SIG_CHANGED[] = "changed";
+static const Evas_Smart_Cb_Description _signals[] = {
+  {SIG_CHANGED, ""},
+  {NULL, NULL}
+};
+
+static Eina_Bool
+_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
+   Evas_Event_Key_Down *ev = event_info;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
+   if (elm_widget_disabled_get(obj)) return EINA_FALSE;
+   if ((strcmp(ev->keyname, "Return")) &&
+       (strcmp(ev->keyname, "KP_Enter")) &&
+       (strcmp(ev->keyname, "space")))
+     return EINA_FALSE;
+   elm_toggle_state_set(obj, !wd->state);
+   evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
+   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   return EINA_TRUE;
+}
+
+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);
+   if (wd->ontext) eina_stringshare_del(wd->ontext);
+   if (wd->offtext) eina_stringshare_del(wd->offtext);
+   free(wd);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (elm_widget_disabled_get(obj))
+     edje_object_signal_emit(wd->tgl, "elm,state,disabled", "elm");
+   else
+     edje_object_signal_emit(wd->tgl, "elm,state,enabled", "elm");
+}
+
+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))
+     {
+       edje_object_signal_emit(wd->tgl, "elm,action,focus", "elm");
+       evas_object_focus_set(wd->tgl, EINA_TRUE);
+     }
+   else
+     {
+       edje_object_signal_emit(wd->tgl, "elm,action,unfocus", "elm");
+       evas_object_focus_set(wd->tgl, EINA_FALSE);
+     }
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->tgl, "toggle", "base", elm_widget_style_get(obj));
+   if (wd->icon)
+     edje_object_signal_emit(wd->tgl, "elm,state,icon,visible", "elm");
+   else
+     edje_object_signal_emit(wd->tgl, "elm,state,icon,hidden", "elm");
+   if (wd->state)
+     edje_object_signal_emit(wd->tgl, "elm,state,toggle,on", "elm");
+   else
+     edje_object_signal_emit(wd->tgl, "elm,state,toggle,off", "elm");
+   if (wd->label)
+     edje_object_signal_emit(wd->tgl, "elm,state,text,visible", "elm");
+   else
+     edje_object_signal_emit(wd->tgl, "elm,state,text,hidden", "elm");
+   edje_object_part_text_set(wd->tgl, "elm.text", wd->label);
+   edje_object_part_text_set(wd->tgl, "elm.ontext", wd->ontext);
+   edje_object_part_text_set(wd->tgl, "elm.offtext", wd->offtext);
+   if (elm_widget_disabled_get(obj))
+     edje_object_signal_emit(wd->tgl, "elm,state,disabled", "elm");
+   edje_object_message_signal_process(wd->tgl);
+   edje_object_scale_set(wd->tgl, 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;
+
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->tgl, &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, -1, -1);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (obj != wd->icon) 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;
+   if (sub == wd->icon)
+     {
+       edje_object_signal_emit(wd->tgl, "elm,state,icon,hidden", "elm");
+       evas_object_event_callback_del_full
+         (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+       wd->icon = NULL;
+       edje_object_message_signal_process(wd->tgl);
+       _sizing_eval(obj);
+     }
+}
+
+static void
+_signal_toggle_off(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->state = 0;
+   if (wd->statep) *wd->statep = wd->state;
+   evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
+}
+
+static void
+_signal_toggle_on(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   wd->state = 1;
+   if (wd->statep) *wd->statep = wd->state;
+   evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
+}
+
+/**
+ * Add a toggle to @p parent.
+ *
+ * @param parent The parent object
+ *
+ * @return The toggle object
+ *
+ * @ingroup Toggle
+ */
+EAPI Evas_Object *
+elm_toggle_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "toggle");
+   elm_widget_type_set(obj, "toggle");
+   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_theme_hook_set(obj, _theme_hook);
+   elm_widget_disable_hook_set(obj, _disable_hook);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+   elm_widget_event_hook_set(obj, _event_hook);
+
+   wd->tgl = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->tgl, "toggle", "base", "default");
+   wd->ontext = eina_stringshare_add("ON");
+   wd->offtext = eina_stringshare_add("OFF");
+   edje_object_signal_callback_add(wd->tgl, "elm,action,toggle,on", "",
+                                   _signal_toggle_on, obj);
+   edje_object_signal_callback_add(wd->tgl, "elm,action,toggle,off", "",
+                                   _signal_toggle_off, obj);
+   elm_widget_resize_object_set(obj, wd->tgl);
+   edje_object_part_text_set(wd->tgl, "elm.ontext", wd->ontext);
+   edje_object_part_text_set(wd->tgl, "elm.offtext", wd->offtext);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _sizing_eval(obj);
+
+   // TODO: convert Elementary to subclassing of Evas_Smart_Class
+   // TODO: and save some bytes, making descriptions per-class and not instance!
+   evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   return obj;
+}
+
+/**
+ * Sets the label to be displayed with the toggle.
+ *
+ * @param obj The toggle object
+ * @param label The label to be displayed
+ *
+ * @ingroup Toggle
+ */
+EAPI void
+elm_toggle_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);
+   if (label)
+     edje_object_signal_emit(wd->tgl, "elm,state,text,visible", "elm");
+   else
+     edje_object_signal_emit(wd->tgl, "elm,state,text,hidden", "elm");
+   edje_object_message_signal_process(wd->tgl);
+   edje_object_part_text_set(wd->tgl, "elm.text", label);
+   _sizing_eval(obj);
+}
+
+/**
+ * Gets the label of the toggle
+ *
+ * @param obj  toggleeee object
+ * @return The label of the toggle
+ *
+ * @ingroup Toggle
+ */
+EAPI const char *
+elm_toggle_label_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->label;
+}
+
+/**
+ * Set the icon used for the toggle
+ *
+ * Once the icon object is set, a previously set one will be deleted
+ * If you want to keep that old content object, use the
+ * elm_toggle_icon_unset() function.
+ *
+ * @param obj The toggle object
+ * @param icon The icon object for the button
+ *
+ * @ingroup Toggle
+ */
+EAPI void
+elm_toggle_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);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+             _changed_size_hints, obj);
+       edje_object_part_swallow(wd->tgl, "elm.swallow.content", icon);
+       edje_object_signal_emit(wd->tgl, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->tgl);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the icon used for the toggle
+ *
+ * Return the icon object which is set for this widget.
+ *
+ * @param obj The toggle object
+ * @return The icon object that is being used
+ *
+ * @ingroup Toggle
+ */
+EAPI Evas_Object *
+elm_toggle_icon_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->icon;
+}
+
+/**
+ * Unset the icon used for the toggle
+ *
+ * Unparent and return the icon object which was set for this widget.
+ *
+ * @param obj The toggle object
+ * @return The icon object that was being used
+ *
+ * @ingroup Toggle
+ */
+EAPI Evas_Object *
+elm_toggle_icon_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->icon) return NULL;
+   Evas_Object *icon = wd->icon;
+   elm_widget_sub_object_del(obj, wd->icon);
+   edje_object_part_unswallow(wd->tgl, wd->icon);
+   wd->icon = NULL;
+   return icon;
+}
+
+/**
+ * Sets the labels to be associated with the on and off states of the toggle.
+ *
+ * @param obj The toggle object
+ * @param onlabel The label displayed when the toggle is in the "on" state
+ * @param offlabel The label displayed when the toggle is in the "off" state
+ *
+ * @ingroup Toggle
+ */
+EAPI void
+elm_toggle_states_labels_set(Evas_Object *obj, const char *onlabel, const char *offlabel)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->ontext, onlabel);
+   eina_stringshare_replace(&wd->offtext, offlabel);
+   edje_object_part_text_set(wd->tgl, "elm.ontext", onlabel);
+   edje_object_part_text_set(wd->tgl, "elm.offtext", offlabel);
+   _sizing_eval(obj);
+}
+
+
+/**
+ * Gets the labels associated with the on and off states of the toggle.
+ *
+ * @param obj The toggle object
+ * @param onlabel A char** to place the onlabel of @p obj into
+ * @param offlabel A char** to place the offlabel of @p obj into
+ *
+ * @ingroup Toggle
+ */
+EAPI void
+elm_toggle_states_labels_get(const Evas_Object *obj, const char **onlabel, const char **offlabel)
+{
+   if (onlabel) *onlabel = NULL;
+   if (offlabel) *offlabel = NULL;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (onlabel) *onlabel = wd->ontext;
+   if (offlabel) *offlabel = wd->offtext;
+}
+
+/**
+ * Sets the state of the toggle to @p state.
+ *
+ * @param obj The toggle object
+ * @param state The state of @p obj
+ *
+ * @ingroup Toggle
+ */
+EAPI void
+elm_toggle_state_set(Evas_Object *obj, Eina_Bool state)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (state != wd->state)
+     {
+       wd->state = state;
+       if (wd->statep) *wd->statep = wd->state;
+       if (wd->state)
+         edje_object_signal_emit(wd->tgl, "elm,state,toggle,on", "elm");
+       else
+         edje_object_signal_emit(wd->tgl, "elm,state,toggle,off", "elm");
+     }
+}
+
+/**
+ * Gets the state of the toggle to @p state.
+ *
+ * @param obj The toggle object
+ * @return The state of @p obj
+ *
+ * @ingroup Toggle
+ */
+EAPI Eina_Bool
+elm_toggle_state_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->state;
+}
+
+/**
+ * Sets the state pointer of the toggle to @p statep.
+ *
+ * @param obj The toggle object
+ * @param statep The state pointer of @p obj
+ *
+ * @ingroup Toggle
+ */
+EAPI void
+elm_toggle_state_pointer_set(Evas_Object *obj, Eina_Bool *statep)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (statep)
+     {
+       wd->statep = statep;
+       if (*wd->statep != wd->state)
+         {
+            wd->state = *wd->statep;
+            if (wd->state)
+              edje_object_signal_emit(wd->tgl, "elm,state,toggle,on", "elm");
+            else
+              edje_object_signal_emit(wd->tgl, "elm,state,toggle,off", "elm");
+         }
+     }
+   else
+     wd->statep = NULL;
+}
diff --git a/src/lib/elm_toolbar.c b/src/lib/elm_toolbar.c
new file mode 100644 (file)
index 0000000..3031216
--- /dev/null
@@ -0,0 +1,2250 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Toolbar Toolbar
+ *
+ * A toolbar is a widget that displays a list of buttons inside
+ * a box.  It is scrollable, and only one item can be selected at a time.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *scr, *bx;
+   Evas_Object *menu_parent;
+   Eina_Inlist *items;
+   Elm_Toolbar_Item *more_item, *selected_item;
+   Elm_Toolbar_Shrink_Mode shrink_mode;
+   Elm_Icon_Lookup_Order lookup_order;
+   int icon_size;
+   double align;
+   Eina_Bool homogeneous : 1;
+   Eina_Bool no_select : 1;
+   Ecore_Job *resize_job;
+};
+
+struct _Elm_Toolbar_Item
+{
+   Elm_Widget_Item base;
+   EINA_INLIST;
+   const char *label;
+   const char *icon_str;
+   Evas_Object *icon;
+   Evas_Object *o_menu;
+   Evas_Smart_Cb func;
+   struct {
+      int priority;
+      Eina_Bool visible : 1;
+   } prio;
+   Eina_Bool selected : 1;
+   Eina_Bool disabled : 1;
+   Eina_Bool separator : 1;
+   Eina_Bool menu : 1;
+   Eina_List *states;
+   Eina_List *current_state;
+};
+
+#define ELM_TOOLBAR_ITEM_FROM_INLIST(item)      \
+  ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Toolbar_Item) : NULL)
+
+struct _Elm_Toolbar_Item_State
+{
+   const char *label;
+   const char *icon_str;
+   Evas_Object *icon;
+   Evas_Smart_Cb func;
+   const void *data;
+};
+
+static const char *widtype = NULL;
+static void _item_show(Elm_Toolbar_Item *it);
+static void _item_select(Elm_Toolbar_Item *it);
+static void _item_unselect(Elm_Toolbar_Item *it);
+static void _item_disable(Elm_Toolbar_Item *it, Eina_Bool disabled);
+static void _del_pre_hook(Evas_Object *obj);
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _menu_move_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _menu_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
+static void _elm_toolbar_item_icon_obj_set(Evas_Object *obj, Elm_Toolbar_Item *item, Evas_Object *icon_obj, const char *icon_str, double icon_size, const char *signal);
+static void _item_label_set(Elm_Toolbar_Item *item, const char *label, const char *signal);
+
+static Eina_Bool
+_item_icon_set(Evas_Object *icon_obj, const char *type, const char *icon)
+{
+   char icon_str[512];
+
+   if ((!type) || (!*type)) goto end;
+   if ((!icon) || (!*icon)) return EINA_FALSE;
+   if ((snprintf(icon_str, sizeof(icon_str), "%s%s", type, icon) > 0)
+       && (elm_icon_standard_set(icon_obj, icon_str)))
+     return EINA_TRUE;
+end:
+   if (elm_icon_standard_set(icon_obj, icon))
+     return EINA_TRUE;
+   WRN("couldn't find icon definition for '%s'", icon);
+   return EINA_FALSE;
+}
+
+static int
+_elm_toolbar_icon_size_get(Widget_Data *wd)
+{
+   const char *icon_size = edje_object_data_get(
+      elm_smart_scroller_edje_object_get(wd->scr), "icon_size");
+   if (icon_size)
+      return atoi(icon_size);
+   return _elm_config->icon_size;
+}
+
+static void
+_item_show(Elm_Toolbar_Item *it)
+{
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   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.view, &x, &y, &w, &h);
+   elm_smart_scroller_child_region_show(wd->scr, x - bx, y - by, w, h);
+}
+
+static void
+_item_unselect(Elm_Toolbar_Item *item)
+{
+   Widget_Data *wd;
+   if ((!item) || (!item->selected)) return;
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+   item->selected = EINA_FALSE;
+   wd->selected_item = NULL;
+   edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm");
+   elm_widget_signal_emit(item->icon, "elm,state,unselected", "elm");
+}
+
+static void
+_item_select(Elm_Toolbar_Item *it)
+{
+   Elm_Toolbar_Item *it2;
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+   Evas_Object *obj2;
+
+   if (!wd) return;
+   if ((it->selected) || (it->disabled) || (it->separator)) return;
+
+   if (!wd->no_select)
+     {
+        it2 = elm_toolbar_selected_item_get(it->base.widget);
+        _item_unselect(it2);
+
+        it->selected = EINA_TRUE;
+        wd->selected_item = it;
+        edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
+        elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
+        _item_show(it);
+     }
+   obj2 = it->base.widget;
+   if (it->menu)
+     {
+        evas_object_show(it->o_menu);
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
+                                       _menu_move_resize, it);
+        evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOVE,
+                                       _menu_move_resize, it);
+
+        _menu_move_resize(it, NULL, NULL, NULL);
+     }
+   if (it->func) it->func((void *)(it->base.data), it->base.widget, it);
+   evas_object_smart_callback_call(obj2, "clicked", it);
+}
+
+static void
+_menu_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Toolbar_Item *selected;
+   Elm_Toolbar_Item *it = data;
+   selected = elm_toolbar_selected_item_get(it->base.widget);
+   _item_unselect(selected);
+}
+
+static void
+_menu_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   // avoid hide being emitted during object deletion
+   evas_object_event_callback_del_full
+     (obj, EVAS_CALLBACK_HIDE, _menu_hide, data);
+}
+
+static void
+_menu_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+    Elm_Toolbar_Item *it = data;
+    Evas_Coord x,y,w,h;
+    Widget_Data *wd = elm_widget_data_get(it->base.widget);
+
+    if ((!wd) || (!wd->menu_parent)) return;
+    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
+    elm_menu_move(it->o_menu, x, y+h);
+}
+
+static void
+_item_disable(Elm_Toolbar_Item *it, Eina_Bool disabled)
+{
+   Widget_Data *wd = elm_widget_data_get(it->base.widget);
+
+   if (!wd) return;
+   if (it->disabled == disabled) return;
+   it->disabled = disabled;
+   if (it->disabled)
+     {
+        edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
+        elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
+     }
+   else
+     {
+        edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
+        elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
+     }
+}
+
+static void
+_item_del(Elm_Toolbar_Item *it)
+{
+   Elm_Toolbar_Item_State *it_state;
+   _item_unselect(it);
+   elm_widget_item_pre_notify_del(it);
+   EINA_LIST_FREE(it->states, it_state)
+     {
+        if (it->icon == it_state->icon)
+           it->icon = NULL;
+        eina_stringshare_del(it_state->label);
+        eina_stringshare_del(it_state->icon_str);
+        if (it_state->icon) evas_object_del(it_state->icon);
+        free(it_state);
+     }
+   eina_stringshare_del(it->label);
+   eina_stringshare_del(it->icon_str);
+   if (it->icon) evas_object_del(it->icon);
+   //TODO: See if checking for wd->menu_parent is necessary before deleting menu
+   if (it->o_menu) evas_object_del(it->o_menu);
+   elm_widget_item_del(it);
+}
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Toolbar_Item *it, *next;
+
+   if (!wd) return;
+   it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
+   while(it)
+     {
+        next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
+        _item_del(it);
+        it = next;
+     }
+   if (wd->more_item)
+      _item_del(wd->more_item);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   free(wd);
+}
+
+
+static void
+_theme_hook_item(Evas_Object *obj, Elm_Toolbar_Item *it, double scale, int icon_size)
+{
+   Evas_Object *view = it->base.view;
+   Evas_Coord mw, mh;
+   const char *style = elm_widget_style_get(obj);
+
+   edje_object_scale_set(view, scale);
+   if (!it->separator)
+     {
+        _elm_theme_object_set(obj, view, "toolbar", "item", style);
+        if (it->selected)
+          {
+             edje_object_signal_emit(view, "elm,state,selected", "elm");
+             elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
+          }
+        if (it->disabled)
+          {
+             edje_object_signal_emit(view, "elm,state,disabled", "elm");
+             elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
+          }
+        if (it->icon)
+          {
+             int ms = 0;
+
+             ms = ((double)icon_size * scale);
+             evas_object_size_hint_min_set(it->icon, ms, ms);
+             evas_object_size_hint_max_set(it->icon, ms, ms);
+             edje_object_part_swallow(view, "elm.swallow.icon",
+                                      it->icon);
+          }
+        edje_object_part_text_set(view, "elm.text", it->label);
+     }
+   else
+      _elm_theme_object_set(obj, view, "toolbar", "separator", style);
+
+   mw = mh = -1;
+   if (!it->separator)
+      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   edje_object_size_min_restricted_calc(view, &mw, &mh, mw, mh);
+   if (!it->separator)
+      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   evas_object_size_hint_min_set(view, mw, mh);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Toolbar_Item *it;
+   double scale = 0;
+
+   if (!wd) return;
+   elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", elm_widget_style_get(obj));
+   scale = (elm_widget_scale_get(obj) * _elm_config->scale);
+   edje_object_scale_set(wd->scr, scale);
+   wd->icon_size = _elm_toolbar_icon_size_get(wd);
+   EINA_INLIST_FOREACH(wd->items, it)
+      _theme_hook_item(obj, it, scale, wd->icon_size);
+   if (wd->more_item)
+      _theme_hook_item(obj, wd->more_item, scale, wd->icon_size);
+   _sizing_eval(obj);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1, minw_bx;
+   Evas_Coord vw = 0, vh = 0;
+   Evas_Coord w, h;
+
+   if (!wd) return;
+   evas_object_smart_calculate(wd->bx);
+   edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
+                             &minw, &minh);
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   if (w < minw) w = minw;
+   if (h < minh) h = minh;
+
+   evas_object_resize(wd->scr, w, h);
+
+   evas_object_size_hint_min_get(wd->bx, &minw, &minh);
+   minw_bx = minw;
+   if (w > minw) minw = w;
+   evas_object_resize(wd->bx, minw, minh);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
+   switch (wd->shrink_mode)
+     {
+       case ELM_TOOLBAR_SHRINK_MENU: /* fallthrough */
+       case ELM_TOOLBAR_SHRINK_HIDE: /* fallthrough */
+       case ELM_TOOLBAR_SHRINK_SCROLL: minw = w - vw; break;
+       case ELM_TOOLBAR_SHRINK_NONE: minw = minw_bx + (w - vw); break;
+     }
+   minh = minh + (h - vh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_item_menu_create(Widget_Data *wd, Elm_Toolbar_Item *item)
+{
+   item->o_menu = elm_menu_add(item->base.view);
+   if (wd->menu_parent)
+     elm_menu_parent_set(item->o_menu, wd->menu_parent);
+   evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_HIDE,
+                                  _menu_hide, item);
+   evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_DEL,
+                                  _menu_del, item);
+}
+
+static void
+_item_menu_destroy(Elm_Toolbar_Item *item)
+{
+   if (item->o_menu)
+     {
+        evas_object_del(item->o_menu);
+        item->o_menu = NULL;
+     }
+}
+
+static int
+_toolbar_item_prio_compare_cb(const void *i1, const void *i2)
+{
+   const Elm_Toolbar_Item *eti1 = i1;
+   const Elm_Toolbar_Item *eti2 = i2;
+
+   if (!eti2) return 1;
+   if (!eti1) return -1;
+
+   return eti2->prio.priority - eti1->prio.priority;
+}
+
+static void
+_fix_items_visibility(Widget_Data *wd, Evas_Coord *iw, Evas_Coord vw)
+{
+   Elm_Toolbar_Item *it;
+   Eina_List *sorted = NULL;
+   Evas_Coord ciw;
+
+   EINA_INLIST_FOREACH(wd->items, it)
+     {
+        sorted = eina_list_sorted_insert(sorted,
+                                         _toolbar_item_prio_compare_cb, it);
+     }
+
+   if (wd->more_item)
+     {
+        evas_object_geometry_get(wd->more_item->base.view, NULL, NULL, &ciw, NULL);
+        *iw += ciw;
+     }
+   EINA_LIST_FREE(sorted, it)
+     {
+        evas_object_geometry_get(it->base.view, NULL, NULL, &ciw, NULL);
+        *iw += ciw;
+        it->prio.visible = (*iw <= vw);
+     }
+}
+
+static void
+_elm_toolbar_item_menu_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Toolbar_Item *it = data;
+   if (it->func) it->func((void *)(it->base.data), it->base.widget, it);
+}
+
+static void
+_resize_job(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord mw, mh, vw, vh, w, h;
+   Elm_Toolbar_Item *it;
+
+   if (!wd) return;
+   wd->resize_job = NULL;
+   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 (wd->shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
+     {
+        Evas_Coord iw = 0, more_w;
+
+        evas_object_resize(wd->bx, vw, h);
+        _fix_items_visibility(wd, &iw, vw);
+        evas_object_geometry_get(wd->more_item->base.view, NULL, NULL, &more_w, NULL);
+        if (iw - more_w <= vw)
+           iw -= more_w;
+
+        /* All items are removed from the box object, since removing individual
+         * items won't trigger a resize. Items are be readded below. */
+        evas_object_box_remove_all(wd->bx, EINA_FALSE);
+        if (iw > vw)
+          {
+             Evas_Object *menu;
+
+             _item_menu_destroy(wd->more_item);
+             _item_menu_create(wd, wd->more_item);
+             menu = elm_toolbar_item_menu_get(wd->more_item);
+
+             EINA_INLIST_FOREACH(wd->items, it)
+               {
+                 if (!it->prio.visible)
+                    {
+                       if (it->separator)
+                         elm_menu_item_separator_add(menu, NULL);
+                       else
+                         {
+                            Elm_Menu_Item *item;
+                            item = elm_menu_item_add(menu, NULL, it->icon_str, it->label,
+                                                     _elm_toolbar_item_menu_cb, it);
+                            elm_menu_item_disabled_set(item, it->disabled);
+                            if (it->o_menu) elm_menu_clone(it->o_menu, menu, item);
+                         }
+                       evas_object_hide(it->base.view);
+                    }
+                 else
+                    {
+                       evas_object_box_append(wd->bx, it->base.view);
+                       evas_object_show(it->base.view);
+                    }
+               }
+
+             evas_object_box_append(wd->bx, wd->more_item->base.view);
+             evas_object_show(wd->more_item->base.view);
+          }
+        else
+          {
+             /* All items are visible, show them all (except for the "More"
+              * button, of course). */
+             EINA_INLIST_FOREACH(wd->items, it)
+               {
+                  evas_object_show(it->base.view);
+                  evas_object_box_append(wd->bx, it->base.view);
+               }
+             evas_object_hide(wd->more_item->base.view);
+          }
+     }
+   else if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
+     {
+        Evas_Coord iw = 0;
+
+        evas_object_resize(wd->bx, vw, h);
+        _fix_items_visibility(wd, &iw, vw);
+        evas_object_box_remove_all(wd->bx, EINA_FALSE);
+        if (iw > vw)
+          {
+             EINA_INLIST_FOREACH(wd->items, it)
+               {
+                 if (!it->prio.visible)
+                   evas_object_hide(it->base.view);
+                 else
+                   {
+                      evas_object_box_append(wd->bx, it->base.view);
+                      evas_object_show(it->base.view);
+                   }
+               }
+          }
+        else
+          {
+             /* All items are visible, show them all */
+             EINA_INLIST_FOREACH(wd->items, it)
+               {
+                  evas_object_show(it->base.view);
+                  evas_object_box_append(wd->bx, it->base.view);
+               }
+          }
+     }
+   else
+     {
+        if ((vw >= mw) && (w != vw)) evas_object_resize(wd->bx, vw, h);
+        EINA_INLIST_FOREACH(wd->items, it)
+          {
+             if (it->selected)
+               {
+                  _item_show(it);
+                  break;
+               }
+          }
+     }
+}
+
+static void
+_resize_item(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _sizing_eval(data);
+   _resize(data, NULL, NULL, NULL);
+}
+
+static void
+_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd->resize_job)
+      wd->resize_job = ecore_job_add(_resize_job, data);
+}
+
+static void
+_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _item_select(data);
+}
+
+static void
+_mouse_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Elm_Toolbar_Item *it = data;
+   edje_object_signal_emit(it->base.view, "elm,state,highlighted", "elm");
+   elm_widget_signal_emit(it->icon, "elm,state,highlighted", "elm");
+}
+
+static void
+_mouse_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Elm_Toolbar_Item *it = data;
+   edje_object_signal_emit(it->base.view, "elm,state,unhighlighted", "elm");
+   elm_widget_signal_emit(it->icon, "elm,state,unhighlighted", "elm");
+}
+
+static void
+_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
+{
+   Widget_Data *wd = data;
+   if (!wd) return;
+   _els_box_layout(o, priv, 1, wd->homogeneous);
+}
+
+static Elm_Toolbar_Item *
+_item_new(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *icon_obj;
+   Evas_Coord mw, mh;
+   Elm_Toolbar_Item *it;
+
+   icon_obj = elm_icon_add(obj);
+   elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
+   if (!icon_obj) return NULL;
+   it = elm_widget_item_new(obj, Elm_Toolbar_Item);
+   if (!it)
+     {
+        evas_object_del(icon_obj);
+        return NULL;
+     }
+   it->label = eina_stringshare_add(label);
+   it->prio.visible = 1;
+   it->prio.priority = 0;
+   it->func = func;
+   it->separator = EINA_FALSE;
+   it->base.data = data;
+   it->base.view = edje_object_add(evas_object_evas_get(obj));
+   if (_item_icon_set(icon_obj, "toolbar/", icon))
+     {
+        it->icon = icon_obj;
+        it->icon_str = eina_stringshare_add(icon);
+     }
+   else
+     {
+        it->icon = NULL;
+        it->icon_str = NULL;
+        evas_object_del(icon_obj);
+     }
+
+   _elm_theme_object_set(obj, it->base.view, "toolbar", "item",
+                         elm_widget_style_get(obj));
+   edje_object_signal_callback_add(it->base.view, "elm,action,click", "elm",
+                                   _select, it);
+   edje_object_signal_callback_add(it->base.view, "elm,mouse,in", "elm",
+                                  _mouse_in, it);
+   edje_object_signal_callback_add(it->base.view, "elm,mouse,out", "elm",
+                                  _mouse_out, it);
+   elm_widget_sub_object_add(obj, it->base.view);
+   if (it->icon)
+     {
+        int ms = 0;
+
+        ms = ((double)wd->icon_size * _elm_config->scale);
+        evas_object_size_hint_min_set(it->icon, ms, ms);
+        evas_object_size_hint_max_set(it->icon, ms, ms);
+        edje_object_part_swallow(it->base.view, "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.view, "elm.text", it->label);
+   mw = mh = -1;
+   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh);
+   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   evas_object_size_hint_weight_set(it->base.view, -1.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(it->base.view, 0.5, EVAS_HINT_FILL);
+   evas_object_size_hint_min_set(it->base.view, mw, mh);
+   evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
+                                  _resize_item, obj);
+   return it;
+}
+
+/**
+ * Add a toolbar object to @p parent.
+ *
+ * @param parent The parent object
+ *
+ * @return The created object, or NULL on failure
+ *
+ * @ingroup Toolbar
+ */
+EAPI Evas_Object *
+elm_toolbar_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (!e) return NULL;
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "toolbar");
+   elm_widget_type_set(obj, "toolbar");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   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);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->more_item = NULL;
+   wd->selected_item = NULL;
+   wd->scr = elm_smart_scroller_add(e);
+   elm_smart_scroller_widget_set(wd->scr, obj);
+   elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", "default");
+   elm_smart_scroller_bounce_allow_set(wd->scr,
+                                       _elm_config->thumbscroll_bounce_enable,
+                                       EINA_FALSE);
+   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 = _elm_toolbar_icon_size_get(wd);
+
+
+   wd->homogeneous = EINA_TRUE;
+   wd->align = 0.5;
+
+   wd->bx = evas_object_box_add(e);
+   evas_object_size_hint_align_set(wd->bx, wd->align, 0.5);
+   evas_object_box_layout_set(wd->bx, _layout, wd, NULL);
+   elm_widget_sub_object_add(obj, wd->bx);
+   elm_smart_scroller_child_set(wd->scr, wd->bx);
+   evas_object_show(wd->bx);
+
+   elm_toolbar_mode_shrink_set(obj, _elm_config->toolbar_shrink_mode);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
+   evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _resize, obj);
+   elm_toolbar_icon_order_lookup_set(obj, ELM_ICON_LOOKUP_THEME_FDO);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the icon size (in pixels) for the toolbar.
+ *
+ * @param obj The toolbar object
+ * @param icon_size The icon size in pixels
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_icon_size_set(Evas_Object *obj, int icon_size)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->icon_size == icon_size) return;
+   wd->icon_size = icon_size;
+   _theme_hook(obj);
+}
+
+/**
+ * Get the icon size (in pixels) for the toolbar.
+ *
+ * @param obj The toolbar object
+ * @return The icon size in pixels
+ *
+ * @ingroup Toolbar
+ */
+EAPI int
+elm_toolbar_icon_size_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return 0;
+   return wd->icon_size;
+}
+
+/**
+ * Append item to the toolbar
+ *
+ * @param obj The toolbar object
+ * @param icon A string with icon name or the absolute path of an image file.
+ * @param label The label of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item
+ * @return The toolbar item, or NULL upon failure
+ *
+ * @see elm_toolbar_item_icon_set
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_item_append(Evas_Object *obj, const char *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;
+
+   Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
+   if (!it) return NULL;
+
+   wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
+   evas_object_box_append(wd->bx, it->base.view);
+   evas_object_show(it->base.view);
+   _sizing_eval(obj);
+
+   return it;
+}
+
+static void
+_elm_toolbar_item_state_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Toolbar_Item *it = event_info;
+   Elm_Toolbar_Item_State *it_state;
+
+   it_state = eina_list_data_get(it->current_state);
+   if (it_state->func)
+      it_state->func((void *)it_state->data, obj, event_info);
+}
+
+/**
+ * Sets the next @p item state as the current state.
+ *
+ * @param item The item.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item_State *
+elm_toolbar_item_state_next(Elm_Toolbar_Item *item)
+{
+   Widget_Data *wd;
+   Evas_Object *obj;
+   Eina_List *next_state;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+
+   obj = item->base.widget;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!item->states) return NULL;
+
+   next_state = eina_list_next(item->current_state);
+   if (!next_state)
+      next_state = eina_list_next(item->states);
+   return eina_list_data_get(next_state);
+}
+
+/**
+ * Sets the previous @p item state as the current state.
+ *
+ * @param item The item.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item_State *
+elm_toolbar_item_state_prev(Elm_Toolbar_Item *item)
+{
+   Widget_Data *wd;
+   Evas_Object *obj;
+   Eina_List *prev_state;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+
+   obj = item->base.widget;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!item->states) return NULL;
+
+   prev_state = eina_list_prev(item->current_state);
+   if ((!prev_state) || (prev_state == item->states))
+      prev_state = eina_list_last(item->states);
+   return eina_list_data_get(prev_state);
+}
+
+/**
+ * Unset the state of @p it
+ * The default icon and label from this item will be displayed.
+ *
+ * @param it The item.
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_state_unset(Elm_Toolbar_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
+   elm_toolbar_item_state_set(it, NULL);
+}
+
+/**
+ * Sets @p state as the current state of @p it.
+ * If @p state is NULL, it won't select any state and the default icon and
+ * label will be used.
+ *
+ * @param it The item.
+ * @param state The state to use.
+ *
+ * @return True if the state was correctly set.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Eina_Bool
+elm_toolbar_item_state_set(Elm_Toolbar_Item *it, Elm_Toolbar_Item_State *state)
+{
+   Widget_Data *wd;
+   Eina_List *next_state;
+   Elm_Toolbar_Item_State *it_state;
+   Evas_Object *obj;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
+
+   obj = it->base.widget;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   if (!it->states) return EINA_FALSE;
+
+   if (state)
+     {
+        next_state = eina_list_data_find_list(it->states, state);
+        if (!next_state) return EINA_FALSE;
+     }
+   else
+      next_state = it->states;
+
+   if (next_state == it->current_state) return EINA_TRUE;
+
+   it_state = eina_list_data_get(next_state);
+   if (eina_list_data_find(it->current_state, state))
+     {
+        _item_label_set(it, it_state->label, "elm,state,label_set,forward");
+        _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
+                                       wd->icon_size, "elm,state,icon_set,forward");
+     }
+   else
+     {
+        _item_label_set(it, it_state->label, "elm,state,label_set,backward");
+        _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
+                                       wd->icon_size, "elm,state,icon_set,backward");
+     }
+   if (it->disabled)
+        elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
+   else
+        elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
+
+   it->current_state = next_state;
+   return EINA_TRUE;
+}
+
+/**
+ * Get the current state of @p item.
+ * If no state is selected, returns NULL.
+ *
+ * @param item The item.
+ *
+ * @return The state.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item_State *
+elm_toolbar_item_state_get(const Elm_Toolbar_Item *it)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
+   if ((!it->states) || (!it->current_state)) return NULL;
+   if (it->current_state == it->states) return NULL;
+
+   return eina_list_data_get(it->current_state);
+}
+
+static Elm_Toolbar_Item_State *
+_item_state_new(const char *label, const char *icon_str, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
+{
+   Elm_Toolbar_Item_State *it_state;
+   it_state = ELM_NEW(Elm_Toolbar_Item_State);
+   it_state->label = eina_stringshare_add(label);
+   it_state->icon_str = eina_stringshare_add(icon_str);
+   it_state->icon = icon;
+   it_state->func = func;
+   it_state->data = data;
+   return it_state;
+}
+
+/**
+ * Add a new state to @p item
+ *
+ * @param item The item.
+ * @param icon The icon string
+ * @param label The label of the new state
+ * @param func The function to call when the item is clicked when this state is
+ * selected.
+ * @param data The data to associate with the state
+ * @return The toolbar item state, or NULL upon failure
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item_State *
+elm_toolbar_item_state_add(Elm_Toolbar_Item *item, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   Elm_Toolbar_Item_State *it_state;
+   Evas_Object *icon_obj;
+   Evas_Object *obj;
+   Widget_Data *wd;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   obj = item->base.widget;
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return NULL;
+
+   if (!item->states)
+     {
+        it_state = _item_state_new(item->label, item->icon_str, item->icon,
+                                   item->func, item->base.data);
+        item->states = eina_list_append(item->states, it_state);
+        item->current_state = item->states;
+     }
+
+   icon_obj = elm_icon_add(obj);
+   elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
+   if (!icon_obj) goto error_state_add;
+
+   if (!_item_icon_set(icon_obj, "toolbar/", icon))
+     {
+        evas_object_del(icon_obj);
+        icon_obj = NULL;
+        icon = NULL;
+     }
+
+   it_state = _item_state_new(label, icon, icon_obj, func, data);
+   item->states = eina_list_append(item->states, it_state);
+   item->func = _elm_toolbar_item_state_cb;
+   item->base.data = NULL;
+
+   return it_state;
+
+error_state_add:
+   if (item->states && !eina_list_next(item->states))
+     {
+        eina_stringshare_del(item->label);
+        eina_stringshare_del(item->icon_str);
+        free(eina_list_data_get(item->states));
+        eina_list_free(item->states);
+        item->states = NULL;
+     }
+   return NULL;
+}
+
+EAPI Eina_Bool
+elm_toolbar_item_state_del(Elm_Toolbar_Item *item, Elm_Toolbar_Item_State *state)
+{
+   Eina_List *del_state;
+   Elm_Toolbar_Item_State *it_state;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+
+   if (!state) return EINA_FALSE;
+   if (!item->states) return EINA_FALSE;
+
+   del_state = eina_list_data_find_list(item->states, state);
+   if (del_state == item->states) return EINA_FALSE;
+   if (del_state == item->current_state)
+      elm_toolbar_item_state_unset(item);
+
+   eina_stringshare_del(state->label);
+   eina_stringshare_del(state->icon_str);
+   if (state->icon) evas_object_del(state->icon);
+   free(state);
+   item->states = eina_list_remove_list(item->states, del_state);
+   if (item->states && !eina_list_next(item->states))
+     {
+        it_state = eina_list_data_get(item->states);
+        item->base.data = it_state->data;
+        item->func = it_state->func;
+        eina_stringshare_del(it_state->label);
+        eina_stringshare_del(it_state->icon_str);
+        free(eina_list_data_get(item->states));
+        eina_list_free(item->states);
+        item->states = NULL;
+     }
+   return EINA_TRUE;
+}
+
+
+/**
+ * Prepend item to the toolbar
+ *
+ * @param obj The toolbar object
+ * @param icon A string with icon name or the absolute path of an image file.
+ * @param label The label of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item
+ * @return The toolbar item, or NULL upon failure
+ *
+ * @see elm_toolbar_item_icon_set
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_item_prepend(Evas_Object *obj, const char *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;
+
+   Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
+   if (!it) return NULL;
+
+   wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
+   evas_object_box_prepend(wd->bx, it->base.view);
+   evas_object_show(it->base.view);
+   _sizing_eval(obj);
+
+   return it;
+}
+
+/**
+ * Insert item before another in the toolbar
+ *
+ * @param obj The toolbar object
+ * @param before The item to insert before
+ * @param icon A string with icon name or the absolute path of an image file.
+ * @param label The label of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item
+ * @return The toolbar item, or NULL upon failure
+ *
+ * @see elm_toolbar_item_icon_set
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_item_insert_before(Evas_Object *obj, Elm_Toolbar_Item *before, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(before, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
+   if (!it) return NULL;
+
+   wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
+                                            EINA_INLIST_GET(before));
+   evas_object_box_insert_before(wd->bx, it->base.view, before->base.view);
+   evas_object_show(it->base.view);
+   _sizing_eval(obj);
+
+   return it;
+}
+
+/**
+ * Insert item after another in the toolbar
+ *
+ * @param obj The toolbar object
+ * @param after The item to insert after
+ * @param icon A string with icon name or the absolute path of an image file.
+ * @param label The label of the item
+ * @param func The function to call when the item is clicked
+ * @param data The data to associate with the item
+ * @return The toolbar item, or NULL upon failure
+ *
+ * @see elm_toolbar_item_icon_set
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_item_insert_after(Evas_Object *obj, Elm_Toolbar_Item *after, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(after, NULL);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
+   if (!it) return NULL;
+
+   wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
+                                            EINA_INLIST_GET(after));
+   evas_object_box_insert_after(wd->bx, it->base.view, after->base.view);
+   evas_object_show(it->base.view);
+   _sizing_eval(obj);
+
+   return it;
+}
+
+/**
+ * Get the first item in the toolbar
+ *
+ * @param obj The toolbar object
+ * @return The first item, or NULL if none
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_first_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd || !wd->items) return NULL;
+   Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
+   return it;
+}
+
+/**
+ * Get the last item in the toolbar
+ *
+ * @return The last item, or NULL if none
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_last_item_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd || !wd->items) return NULL;
+   Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items->last);
+   return it;
+}
+
+/**
+ * Get the next item in the toolbar
+ *
+ * This returns the item after the item @p it.
+ *
+ * @param item The item
+ * @return The item after @p it, or NULL if none
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_item_next_get(const Elm_Toolbar_Item *item)
+{
+   Elm_Toolbar_Item *next;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
+   return next;
+}
+
+/**
+ * Get the previous item in the toolbar
+ *
+ * This returns the item before the item @p it.
+ *
+ * @param item The item
+ * @return The item before @p it, or NULL if none
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_item_prev_get(const Elm_Toolbar_Item *item)
+{
+   Elm_Toolbar_Item *prev;
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   prev = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
+   return prev;
+}
+
+/**
+ * Get the toolbar object from an item
+ *
+ * This returns the toolbar object itself that an item belongs to.
+ *
+ * @param item The item
+ * @return The toolbar object
+ *
+ * @ingroup Toolbar
+ */
+EAPI Evas_Object *
+elm_toolbar_item_toolbar_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->base.widget;
+}
+
+/**
+ * Sets the priority of a toolbar item. This is used only when the toolbar
+ * shrink mode is set to ELM_TOOLBAR_SHRINK_MENU or ELM_TOOLBAR_SHRINK_HIDE:
+ * when space is at a premium, items with low priority will be removed from
+ * the toolbar and added to a dynamically-created menu, while items with
+ * higher priority will remain on the toolbar, with the same order they were
+ * added.
+ *
+ * @param item The toolbar item.
+ * @param priority The item priority. The default is zero.
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_priority_set(Elm_Toolbar_Item *item, int priority)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+    if (item->prio.priority == priority) return;
+    item->prio.priority = priority;
+    _resize(item->base.widget, NULL, NULL, NULL);
+}
+
+/**
+ * Gets the priority of a toolbar item.
+ *
+ * @param item The toolbar item.
+ * @return The item priority, or 0 if an error occurred.
+ *
+ * @ingroup Toolbar
+ */
+EAPI int
+elm_toolbar_item_priority_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, 0);
+   return item->prio.priority;
+}
+
+/**
+ * Get the string used to set the icon of @p item.
+ *
+ * @param item The toolbar item
+ * @return The string associated with the icon object.
+ *
+ * @see elm_toolbar_item_icon_set()
+ *
+ * @ingroup Toolbar
+ */
+EAPI const char *
+elm_toolbar_item_icon_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->icon_str;
+}
+
+/**
+ * Get the label associated with @p item.
+ *
+ * @param item The toolbar item
+ * @return The label
+ *
+ * @ingroup Toolbar
+ */
+EAPI const char *
+elm_toolbar_item_label_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return item->label;
+}
+
+static void
+_elm_toolbar_item_label_update(Elm_Toolbar_Item *item)
+{
+   Evas_Coord mw = -1, mh = -1;
+   edje_object_part_text_set(item->base.view, "elm.text", item->label);
+
+   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
+   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
+   evas_object_size_hint_min_set(item->base.view, mw, mh);
+}
+
+static void
+_elm_toolbar_item_label_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Elm_Toolbar_Item *item = data;
+   _elm_toolbar_item_label_update(item);
+   edje_object_signal_callback_del(obj, emission, source,
+                                   _elm_toolbar_item_label_set_cb);
+   edje_object_signal_emit (item->base.view, "elm,state,label,reset", "elm");
+}
+
+static void
+_item_label_set(Elm_Toolbar_Item *item, const char *label, const char *signal)
+{
+   const char *s;
+
+   if ((label) && (item->label) && (!strcmp(label, item->label))) return;
+
+   eina_stringshare_replace(&item->label, label);
+   s = edje_object_data_get(item->base.view, "transition_animation_on");
+   if ((s) && (atoi(s)))
+     {
+        edje_object_part_text_set(item->base.view, "elm.text_new", item->label);
+        edje_object_signal_emit (item->base.view, signal, "elm");
+        edje_object_signal_callback_add(item->base.view,
+                                        "elm,state,label_set,done", "elm",
+                                        _elm_toolbar_item_label_set_cb, item);
+     }
+   else
+      _elm_toolbar_item_label_update(item);
+   _resize(item->base.widget, NULL, NULL, NULL);
+}
+
+/**
+ * Set the label associated with @p item.
+ *
+ * @param item The toolbar item
+ * @param label The label of @p item
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_label_set(Elm_Toolbar_Item *item, const char *label)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   _item_label_set(item, label, "elm,state,label_set");
+}
+
+static void
+_elm_toolbar_item_icon_update(Elm_Toolbar_Item *item)
+{
+   Elm_Toolbar_Item_State *it_state;
+   Eina_List *l;
+   Evas_Coord mw = -1, mh = -1;
+   Evas_Object *old_icon = edje_object_part_swallow_get(item->base.view,
+                                                        "elm.swallow.icon");
+   elm_widget_sub_object_del(item->base.view, old_icon);
+   evas_object_hide(old_icon);
+   edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon);
+   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
+   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
+   evas_object_size_hint_min_set(item->base.view, mw, mh);
+
+   EINA_LIST_FOREACH(item->states, l, it_state)
+      if (it_state->icon == old_icon)
+         return;
+   evas_object_del(old_icon);
+}
+
+/**
+ * Get the selected state of @p item.
+ *
+ * @param item The toolbar item
+ * @return If true, the item is selected
+ *
+ * @ingroup Toolbar
+ */
+EAPI Eina_Bool
+elm_toolbar_item_selected_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return item->selected;
+}
+
+/**
+ * Set the selected state of an item
+ *
+ * This sets the selected state (1 selected, 0 not selected) of the given
+ * item @p it. If a new item is selected the previosly selected will be
+ * unselected.
+ *
+ * @param item The item
+ * @param selected The selected state
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_selected_set(Elm_Toolbar_Item *item, Eina_Bool selected)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   Widget_Data *wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+
+   if (item->selected == selected) return;
+
+   if (selected)
+     _item_select(item);
+   else
+     _item_unselect(item);
+}
+
+/**
+ * Get the selectd item in the toolbar
+ *
+ * If no item is selected, NULL is returned.
+ *
+ * @param obj The toolbar object
+ * @return The selected item, or NULL if none.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_selected_item_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_item;
+}
+
+static void
+_elm_toolbar_item_icon_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Elm_Toolbar_Item *item = data;
+   edje_object_part_unswallow(item->base.view, item->icon);
+   _elm_toolbar_item_icon_update(item);
+   edje_object_signal_callback_del(obj, emission, source,
+                                   _elm_toolbar_item_icon_set_cb);
+   edje_object_signal_emit (item->base.view, "elm,state,icon,reset", "elm");
+}
+
+static void
+_elm_toolbar_item_icon_obj_set(Evas_Object *obj, Elm_Toolbar_Item *item, Evas_Object *icon_obj, const char *icon_str, double icon_size, const char *signal)
+{
+   Evas_Object *old_icon;
+   int ms = 0;
+   const char *s;
+
+   if (icon_str)
+      eina_stringshare_replace(&item->icon_str, icon_str);
+   else
+     {
+        eina_stringshare_del(item->icon_str);
+        item->icon_str = NULL;
+     }
+   item->icon = icon_obj;
+   if (icon_obj)
+     {
+        ms = (icon_size * _elm_config->scale);
+        evas_object_size_hint_min_set(item->icon, ms, ms);
+        evas_object_size_hint_max_set(item->icon, ms, ms);
+        evas_object_show(item->icon);
+        elm_widget_sub_object_add(obj, item->icon);
+     }
+   s = edje_object_data_get(item->base.view, "transition_animation_on");
+   if ((s) && (atoi(s)))
+     {
+        old_icon = edje_object_part_swallow_get(item->base.view,
+                                                "elm.swallow.icon_new");
+        if (old_icon)
+          {
+             elm_widget_sub_object_del(item->base.view, old_icon);
+             evas_object_hide(old_icon);
+          }
+        edje_object_part_swallow(item->base.view, "elm.swallow.icon_new",
+                                 item->icon);
+        edje_object_signal_emit (item->base.view, signal, "elm");
+        edje_object_signal_callback_add(item->base.view,
+                                        "elm,state,icon_set,done", "elm",
+                                        _elm_toolbar_item_icon_set_cb, item);
+     }
+   else
+      _elm_toolbar_item_icon_update(item);
+   _resize(obj, NULL, NULL, NULL);
+}
+
+/**
+ * Set the icon associated with @p item.
+ *
+ * Toolbar will load icon image from fdo or current theme.
+ * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
+ * If an absolute path is provided it will load it direct from a file.
+ *
+ * @param obj The parent of this item
+ * @param item The toolbar item
+ * @param icon A string with icon name or the absolute path of an image file.
+ *
+ * @see elm_toolbar_icon_order_lookup_set(), elm_toolbar_icon_order_lookup_get()
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_icon_set(Elm_Toolbar_Item *item, const char *icon)
+{
+   Evas_Object *icon_obj;
+   Widget_Data *wd;
+   Evas_Object *obj = item->base.widget;
+
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((icon) && (item->icon_str) && (!strcmp(icon, item->icon_str))) return;
+
+   icon_obj = elm_icon_add(obj);
+   if (!icon_obj) return;
+   if (_item_icon_set(icon_obj, "toolbar/", icon))
+      _elm_toolbar_item_icon_obj_set(obj, item, icon_obj, icon, wd->icon_size,
+                                     "elm,state,icon_set");
+   else
+     {
+        _elm_toolbar_item_icon_obj_set(obj, item, NULL, NULL, 0,
+                                       "elm,state,icon_set");
+        evas_object_del(icon_obj);
+     }
+}
+
+/**
+ * Delete a toolbar item.
+ *
+ * @param item The toolbar item
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_del(Elm_Toolbar_Item *item)
+{
+   Widget_Data *wd;
+   Evas_Object *obj2;
+
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+   obj2 = item->base.widget;
+   wd->items = eina_inlist_remove(wd->items, EINA_INLIST_GET(item));
+   _item_del(item);
+   _theme_hook(obj2);
+}
+
+/**
+ * Set the function called when a toolbar item is freed.
+ *
+ * @param item The item to set the callback on
+ * @param func The function called
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_del_cb_set(Elm_Toolbar_Item *item, Evas_Smart_Cb func)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_del_cb_set(item, func);
+}
+
+/**
+ * Get the disabled state of @p item.
+ *
+ * @param item The toolbar item
+ * @return If true, the item is disabled
+ *
+ * @ingroup Toolbar
+ */
+EAPI Eina_Bool
+elm_toolbar_item_disabled_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return item->disabled;
+}
+
+/**
+ * Set the disabled state of @p item.
+ *
+ * @param item The toolbar item
+ * @param disabled If true, the item is disabled
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_disabled_set(Elm_Toolbar_Item *item, Eina_Bool disabled)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   _item_disable(item, disabled);
+   _resize(item->base.widget, NULL, NULL, NULL);
+}
+
+/**
+ * Get the separator state of @p item.
+ *
+ * @param item The toolbar item
+ * @param separator If true, the item is a separator
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_separator_set(Elm_Toolbar_Item *item, Eina_Bool separator)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   if (item->separator == separator) return;
+   item->separator = separator;
+   _theme_hook(item->base.view);
+}
+
+/**
+ * Set the separator state of @p item.
+ *
+ * @param item The toolbar item
+ * @return If true, the item is a separator
+ *
+ * @ingroup Toolbar
+ */
+EAPI Eina_Bool
+elm_toolbar_item_separator_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return item->separator;
+}
+
+/**
+ * Set the shrink state of toolbar @p obj.
+ *
+ * @param obj The toolbar object
+ * @param shrink_mode The toolbar won't scroll if ELM_TOOLBAR_SHRINK_NONE,
+ * but will enforce a minimun size so all the items will fit, won't scroll
+ * and won't show the items that don't fit if ELM_TOOLBAR_SHRINK_HIDE,
+ * will scroll if ELM_TOOLBAR_SHRINK_SCROLL, and will create a button to
+ * pop up excess elements with ELM_TOOLBAR_SHRINK_MENU.
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_mode_shrink_set(Evas_Object *obj, Elm_Toolbar_Shrink_Mode shrink_mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_Bool bounce;
+
+   if (!wd) return;
+   wd->shrink_mode = shrink_mode;
+   bounce = (_elm_config->thumbscroll_bounce_enable) &&
+      (shrink_mode == ELM_TOOLBAR_SHRINK_SCROLL);
+   elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
+
+   if (wd->more_item)
+     {
+        _item_del(wd->more_item);
+        wd->more_item = NULL;
+     }
+
+   if (shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
+     {
+        elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF, ELM_SMART_SCROLLER_POLICY_OFF);
+
+        wd->more_item = _item_new(obj, "more_menu", "More",
+                                                NULL, NULL);
+     }
+   else if (shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
+     elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF,
+                                   ELM_SMART_SCROLLER_POLICY_OFF);
+   else
+     elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_AUTO,
+                                   ELM_SMART_SCROLLER_POLICY_OFF);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the shrink mode of toolbar @p obj.
+ *
+ * @param obj The toolbar object
+ * @return See elm_toolbar_mode_shrink_set.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Shrink_Mode
+elm_toolbar_mode_shrink_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_TOOLBAR_SHRINK_NONE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return ELM_TOOLBAR_SHRINK_NONE;
+   return wd->shrink_mode;
+}
+
+/**
+ * Set the homogenous mode of toolbar @p obj.
+ *
+ * @param obj The toolbar object
+ * @param homogenous If true, the toolbar items will be uniform in size
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   wd->homogeneous = !!homogenous;
+   evas_object_smart_calculate(wd->bx);
+}
+
+/**
+ * Get the homogenous mode of toolbar @p obj.
+ *
+ * @param obj The toolbar object
+ * @return If true, the toolbar items are uniform in size
+ *
+ * @ingroup Toolbar
+ */
+EAPI Eina_Bool
+elm_toolbar_homogenous_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->homogeneous;
+}
+
+/**
+ * Set the parent object of the toolbar menu
+ *
+ * @param obj The toolbar object
+ * @param parent The parent of the menu object
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
+{
+   Elm_Toolbar_Item *it;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   EINA_SAFETY_ON_NULL_RETURN(parent);
+   wd->menu_parent = parent;
+   EINA_INLIST_FOREACH(wd->items, it)
+     {
+        if (it->o_menu)
+          elm_menu_parent_set(it->o_menu, wd->menu_parent);
+     }
+   if ((wd->more_item) && (wd->more_item->o_menu))
+      elm_menu_parent_set(wd->more_item->o_menu, wd->menu_parent);
+}
+
+/**
+ * Get the parent object of the toolbar menu
+ *
+ * @param obj The toolbar object
+ * @return The parent of the menu object
+ *
+ * @ingroup Toolbar
+ */
+EAPI Evas_Object *
+elm_toolbar_menu_parent_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->menu_parent;
+}
+
+/**
+ * Set the alignment of the items.
+ *
+ * @param obj The toolbar object
+ * @param align The new alignment. (left) 0.0 ... 1.0 (right)
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_align_set(Evas_Object *obj, double align)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   if (wd->align != align)
+     evas_object_size_hint_align_set(wd->bx, align, 0.5);
+   wd->align = align;
+}
+
+/**
+ * Get the alignment of the items.
+ *
+ * @param obj The toolbar object
+ * @return The alignment. (left) 0.0 ... 1.0 (right)
+ *
+ * @ingroup Toolbar
+ */
+EAPI double
+elm_toolbar_align_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return 0.0;
+   return wd->align;
+}
+
+/**
+ * Set whether the toolbar item opens a menu.
+ *
+ * @param item The toolbar item
+ * @param menu If true, @p item will open a menu when selected
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_menu_set(Elm_Toolbar_Item *item, Eina_Bool menu)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   Widget_Data *wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return;
+
+   if (item->menu == menu) return;
+   item->menu = menu;
+   if (menu) _item_menu_create(wd, item);
+   else _item_menu_destroy(item);
+}
+
+/**
+ * Set the text to be shown in the toolbar item.
+ *
+ * @param item Target item
+ * @param text The text to set in the content
+ *
+ * Setup the text as tooltip to object. The item can have only one tooltip,
+ * so any previous tooltip data is removed.
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_tooltip_text_set(Elm_Toolbar_Item *item, const char *text)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_text_set(item, text);
+}
+
+/**
+ * Set the content to be shown in the tooltip item
+ *
+ * Setup the tooltip to item. The item can have only one tooltip,
+ * so any previous tooltip data is removed. @p func(with @p data) will
+ * be called every time that need show the tooltip and it should
+ * return a valid Evas_Object. This object is then managed fully by
+ * tooltip system and is deleted when the tooltip is gone.
+ *
+ * @param item the toolbar item being attached a tooltip.
+ * @param func the function used to create the tooltip contents.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_toolbar_item_tooltip_unset() or the owner @a item
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is the item.
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_tooltip_content_cb_set(Elm_Toolbar_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
+}
+
+/**
+ * Unset tooltip from item
+ *
+ * @param item toolbar item to remove previously set tooltip.
+ *
+ * Remove tooltip from item. The callback provided as del_cb to
+ * elm_toolbar_item_tooltip_content_cb_set() will be called to notify
+ * it is not used anymore.
+ *
+ * @see elm_toolbar_item_tooltip_content_cb_set()
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_tooltip_unset(Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_unset(item);
+}
+
+/**
+ * Sets a different style for this item tooltip.
+ *
+ * @note before you set a style you should define a tooltip with
+ *       elm_toolbar_item_tooltip_content_cb_set() or
+ *       elm_toolbar_item_tooltip_text_set()
+ *
+ * @param item toolbar item with tooltip already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_tooltip_style_set(Elm_Toolbar_Item *item, const char *style)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_tooltip_style_set(item, style);
+}
+
+/**
+ * Get the style for this item tooltip.
+ *
+ * @param item toolbar item with tooltip already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a tooltip set, then NULL is returned.
+ *
+ * @ingroup Toolbar
+ */
+EAPI const char *
+elm_toolbar_item_tooltip_style_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_tooltip_style_get(item);
+}
+
+/**
+ * Set the cursor to be shown when mouse is over the toolbar item
+ *
+ * @param item Target item
+ * @param cursor the cursor name to be used.
+ *
+ * @see elm_object_cursor_set()
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_cursor_set(Elm_Toolbar_Item *item, const char *cursor)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_set(item, cursor);
+}
+
+/**
+ * Get the cursor to be shown when mouse is over the toolbar item
+ *
+ * @param item toolbar item with cursor already set.
+ * @return the cursor name.
+ *
+ * @ingroup Toolbar
+ */
+EAPI const char *
+elm_toolbar_item_cursor_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_get(item);
+}
+
+/**
+ * Unset the cursor to be shown when mouse is over the toolbar item
+ *
+ * @param item Target item
+ *
+ * @see elm_object_cursor_unset()
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_cursor_unset(Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_unset(item);
+}
+
+/**
+ * Sets a different style for this item cursor.
+ *
+ * @note before you set a style you should define a cursor with
+ *       elm_toolbar_item_cursor_set()
+ *
+ * @param item toolbar item with cursor already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_cursor_style_set(Elm_Toolbar_Item *item, const char *style)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_style_set(item, style);
+}
+
+/**
+ * Get the style for this item cursor.
+ *
+ * @param item toolbar item with cursor already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup Toolbar
+ */
+EAPI const char *
+elm_toolbar_item_cursor_style_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_cursor_style_get(item);
+}
+
+/**
+ * Set if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a cursor
+ * with elm_object_cursor_set(). By default it will only look for cursors
+ * provided by the engine.
+ *
+ * @param item widget item with cursor already set.
+ * @param engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well.
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_cursor_engine_only_set(Elm_Toolbar_Item *item, Eina_Bool engine_only)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_cursor_engine_only_set(item, engine_only);
+}
+
+/**
+ * Get the cursor engine only usage for this item cursor.
+ *
+ * @param item widget item with cursor already set.
+ * @return engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well. If
+ *         the object does not have a cursor set, then EINA_FALSE is returned.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Eina_Bool
+elm_toolbar_item_cursor_engine_only_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
+   return elm_widget_item_cursor_engine_only_get(item);
+}
+
+/**
+ * Get whether the toolbar item opens a menu.
+ *
+ * @param item The toolbar item
+ * @return If true, @p item opens a menu when selected
+ *
+ * @ingroup Toolbar
+ */
+EAPI Evas_Object *
+elm_toolbar_item_menu_get(Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   Widget_Data *wd = elm_widget_data_get(item->base.widget);
+   if (!wd) return NULL;
+   /* FIXME: It's not ok. This function needs to be reviewed. And should
+    * receive a const item */
+   elm_toolbar_item_menu_set(item, 1);
+   return item->o_menu;
+}
+
+/**
+ * Returns a pointer to a toolbar item by its label
+ *
+ * @param obj The toolbar object
+ * @param label The label of the item to find
+ *
+ * @return The pointer to the toolbar item matching @p label
+ * Returns NULL on failure.
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Toolbar_Item *
+elm_toolbar_item_find_by_label(const Evas_Object *obj, const char *label)
+{
+   Elm_Toolbar_Item *it;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return NULL;
+   EINA_INLIST_FOREACH(wd->items, it)
+     {
+        if (!strcmp(it->label, label)) return it;
+     }
+
+   return NULL;
+}
+
+/**
+ * Set the data item from the toolbar item
+ *
+ * This set the data value passed on the elm_toolbar_item_append() and
+ * related item addition calls.
+ *
+ * @param item The item
+ * @param data The new data pointer to set
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_item_data_set(Elm_Toolbar_Item *item, const void *data)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
+   elm_widget_item_data_set(item, data);
+}
+
+/**
+ * Get the data item from the toolbar item
+ *
+ * This returns the data value passed on the elm_toolbar_item_append() and
+ * related item addition calls.
+ *
+ * @param item The item
+ * @return The data pointer provided when created
+ *
+ * @ingroup Toolbar
+ */
+EAPI void *
+elm_toolbar_item_data_get(const Elm_Toolbar_Item *item)
+{
+   ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
+   return elm_widget_item_data_get(item);
+}
+
+/**
+ * Set no select mode.
+ *
+ * This will turn off the ability to select items entirely and they will
+ * neither appear selected nor emit selected signals. The clicked
+ * callback function will still be called.
+ *
+ * @param obj The Toolbar object
+ * @param no_select The no select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_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 Toolbar object
+ * @return The no select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Toolbar
+ */
+EAPI Eina_Bool
+elm_toolbar_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;
+}
+
+/**
+ * Sets icon lookup order, for icons used in this toolbar.
+ * Icons added before calling this function will not be affected.
+ * The default lookup order is ELM_ICON_LOOKUP_THEME_FDO.
+ *
+ * @param obj The toolbar object
+ * @param order The icon lookup order
+ *
+ * @ingroup Toolbar
+ */
+EAPI void
+elm_toolbar_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Elm_Toolbar_Item *it;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   wd->lookup_order = order;
+   EINA_INLIST_FOREACH(wd->items, it)
+      elm_icon_order_lookup_set(it->icon, order);
+   if (wd->more_item)
+      elm_icon_order_lookup_set(wd->more_item->icon, order);
+}
+
+/**
+ * Gets the icon lookup order.
+ *
+ * @param obj The Toolbar object
+ * @return The icon lookup order
+ *
+ * @ingroup Toolbar
+ */
+EAPI Elm_Icon_Lookup_Order
+elm_toolbar_icon_order_lookup_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
+   return wd->lookup_order;
+}
diff --git a/src/lib/elm_transit.c b/src/lib/elm_transit.c
new file mode 100644 (file)
index 0000000..7319de3
--- /dev/null
@@ -0,0 +1,2664 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define ELM_TRANSIT_CHECK_OR_RETURN(transit, ...) \
+   do { \
+      if (!transit) { \
+         CRITICAL("Elm_Transit " # transit " is NULL!"); \
+         return __VA_ARGS__; \
+      } \
+      if (!EINA_MAGIC_CHECK(transit, ELM_TRANSIT_MAGIC)) { \
+         EINA_MAGIC_FAIL(transit, ELM_TRANSIT_MAGIC); \
+         return __VA_ARGS__; \
+      } \
+      if (transit->deleted){ \
+         ERR("Elm_Transit " # transit " has already been deleted!"); \
+         return __VA_ARGS__; \
+      } \
+   } while (0)
+
+/**
+ *
+ * @defgroup Transit Transit
+ * @ingroup Elementary
+ *
+ * Transit (see Warning below) is designed to set the various effects for the
+ * Evas_Object such like translation, rotation, etc. For using Effects, Create
+ * transit and insert effects which are interesting.
+ * Once effects are inserted into transit, transit will manage those effects.
+ * (ex deleting).
+ *
+ * Example:
+ * @code
+ * Elm_Transit *trans = elm_transit_add();
+ * elm_transit_object_add(trans, obj);
+ * void *effect_context = elm_transit_effect_translation_context_new(0.0, 0.0,
+ *                                                               280.0, 280.0);
+ * elm_transit_effect_add(transit,
+ *                        elm_transit_effect_translation_op, effect_context,
+ *                        elm_transit_effect_translation_context_free);
+ * elm_transit_duration_set(transit, 5);
+ * elm_transit_auto_reverse_set(transit, EINA_TRUE);
+ * elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
+ * elm_transit_repeat_times_set(transit, -1);
+ * @endcode
+ *
+ * @warning We strongly recomend to use elm_transit just when edje can not do
+ * the trick. Edje has more advantage than Elm_Transit, it has more flexibility and
+ * animations can be manipulated inside the theme.
+ */
+
+static const char _transit_key[] = "_elm_transit";
+
+#define FOCAL 2000
+
+struct _Elm_Transit
+{
+#define ELM_TRANSIT_MAGIC 0xd27f190a
+   EINA_MAGIC;
+
+   Ecore_Animator *animator;
+   Eina_List *effect_list;
+   Eina_List *objs;
+   Elm_Transit_Tween_Mode tween_mode;
+   struct {
+      void (*func) (void *data, Elm_Transit *transit);
+      void *arg;
+   } del_data;
+   struct {
+      double delayed;
+      double paused;
+      double duration;
+      double begin;
+      double current;
+   } time;
+   struct {
+      int count;
+      int current;
+      Eina_Bool reverse;
+   } repeat;
+   double progress;
+   unsigned int effects_pending_del;
+   int walking;
+   Eina_Bool auto_reverse : 1;
+   Eina_Bool event_enabled : 1;
+   Eina_Bool deleted : 1;
+};
+
+struct _Elm_Transit_Effect
+{
+   void (*animation_op) (void *data, Elm_Transit *transit, double progress);
+   void (*user_data_free) (void *data, Elm_Transit *transit);
+   void *user_data;
+   Eina_Bool deleted : 1;
+};
+
+struct _Elm_Obj_Data
+{
+   Eina_Bool state;
+   Elm_Transit *transit;
+};
+
+typedef struct _Elm_Transit_Effect Elm_Transit_Effect;
+typedef struct _Elm_Obj_Data Elm_Obj_Data;
+
+static void
+_elm_transit_object_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *transit = data;
+
+   Elm_Obj_Data *obj_data = evas_object_data_del(obj, _transit_key);
+   evas_object_pass_events_set(obj, obj_data->state);
+   free(obj_data);
+   transit->objs = eina_list_remove(transit->objs, obj);
+   if (!transit->objs) elm_transit_del(transit);
+}
+
+static void
+_elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
+{
+   Elm_Obj_Data *obj_data = evas_object_data_del(obj, _transit_key);
+   
+   evas_object_pass_events_set(obj, obj_data->state);
+   free(obj_data);
+   transit->objs = eina_list_remove(transit->objs, obj);
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
+                                  _elm_transit_object_remove_cb);
+}
+
+static void
+_elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect *effect, Eina_List *elist)
+{
+   if (effect->user_data_free)
+      effect->user_data_free(effect->user_data, transit);
+
+   transit->effect_list = eina_list_remove_list(transit->effect_list, elist);
+   free(effect);
+}
+
+static void
+_remove_dead_effects(Elm_Transit *transit)
+{
+   Eina_List *elist, *elist_next;
+   Elm_Transit_Effect *effect;
+
+   EINA_LIST_FOREACH_SAFE(transit->effect_list, elist, elist_next, effect)
+     {
+        if (effect->deleted)
+          {
+             _elm_transit_effect_del(transit, effect, elist);
+             transit->effects_pending_del--;
+             if (!transit->effects_pending_del) return;
+          }
+     }
+}
+
+static void
+_elm_transit_del(Elm_Transit *transit)
+{
+   Eina_List *elist, *elist_next;
+   Elm_Transit_Effect *effect;
+
+   if (transit->animator)
+      ecore_animator_del(transit->animator);
+
+   if (transit->del_data.func)
+      transit->del_data.func(transit->del_data.arg, transit);
+
+   EINA_LIST_FOREACH_SAFE(transit->effect_list, elist, elist_next, effect)
+      _elm_transit_effect_del(transit, effect, elist);
+   
+   while (transit->objs)
+      _elm_transit_object_remove(transit, eina_list_data_get(transit->objs));
+   
+   EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
+   free(transit);
+}
+
+static void
+_transit_animate_op(Elm_Transit *transit, double progress)
+{
+   Eina_List *elist;
+   Elm_Transit_Effect *effect;
+
+   transit->walking++;
+   EINA_LIST_FOREACH(transit->effect_list, elist, effect)
+     {
+        if (transit->deleted) break;
+        if (!effect->deleted)
+           effect->animation_op(effect->user_data, transit, progress);
+     }
+   transit->walking--;
+   
+   if (transit->walking) return;
+   
+   if (transit->deleted) _elm_transit_del(transit);
+   else if (transit->effects_pending_del) _remove_dead_effects(transit);
+}
+
+static Eina_Bool
+_animator_animate_cb(void *data)
+{
+   Elm_Transit *transit = data;
+   double elapsed_time, duration;
+
+   transit->time.current = ecore_loop_time_get();
+   elapsed_time = transit->time.current - transit->time.begin;
+   duration = transit->time.duration + transit->time.delayed; 
+
+   if (elapsed_time > duration) 
+      elapsed_time = duration;
+
+   transit->progress = elapsed_time / duration;
+   switch (transit->tween_mode)
+     {
+      case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
+        transit->progress = 1.0 - sin((ELM_PI / 2.0) + (transit->progress * ELM_PI / 2.0));
+        break;
+      case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
+        transit->progress = sin(transit->progress * ELM_PI / 2.0);
+        break;
+      case ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL:
+        transit->progress = (1.0 - cos(transit->progress * ELM_PI)) / 2.0;
+        break;
+      default:
+        break;
+     }
+   
+   /* Reverse? */
+   if (transit->repeat.reverse) transit->progress = 1 - transit->progress;
+   
+   if (transit->time.duration > 0) _transit_animate_op(transit, transit->progress);
+   
+   /* Not end. Keep going. */
+   if (elapsed_time < duration) return ECORE_CALLBACK_RENEW;
+
+   /* Repeat and reverse and time done! */
+   if ((transit->repeat.current == transit->repeat.count)
+       && (!transit->auto_reverse || transit->repeat.reverse))
+     {
+        elm_transit_del(transit);
+       return ECORE_CALLBACK_CANCEL;
+     }
+   
+   /* Repeat Case */
+   if (!transit->auto_reverse || transit->repeat.reverse)
+     {
+        transit->repeat.current++;
+        transit->repeat.reverse = EINA_FALSE;
+     }
+   else transit->repeat.reverse = EINA_TRUE;
+   
+   transit->time.begin = ecore_loop_time_get();
+   
+   return ECORE_CALLBACK_RENEW;
+}
+
+/**
+ * Add new transit.
+ *
+ * @note Is not necessary to delete the transit object, it will be deleted at
+ * the end of its operation.
+ * @note The transit will start playing when the program enter in the main loop, is not
+ * necessary to give a start to the transit.
+ *
+ * @param duration The duration of the transit in seconds. When transit starts
+ * to run, it will last a @p duration time.
+ * @return The transit object.
+ *
+ * @ingroup Transit
+ */
+EAPI Elm_Transit *
+elm_transit_add(void)
+{
+   Elm_Transit *transit = ELM_NEW(Elm_Transit);
+   if (!transit) return NULL;
+   
+   EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
+
+   elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
+       
+   return transit;
+}
+/**
+ * Stops the animation and delete the @p transit object.
+ *
+ * Call this function if you wants to stop the animation before the duration
+ * time. Make sure the @p transit object is still alive with
+ * elm_transit_del_cb_set() function.
+ * All added effects will be deleted, calling its repective data_free_cb
+ * functions. The function setted by elm_tansit_del_cb_set() will be called.
+ *
+ * @see elm_transit_del_cb_set()
+ *
+ * @param transit The transit object to be deleted.
+ *
+ * @ingroup Transit
+ * @warning Just call this function if you are sure the transit is alive.
+ */
+EAPI void
+elm_transit_del(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+
+   if (transit->walking) transit->deleted = EINA_TRUE;
+   else _elm_transit_del(transit);
+}
+
+/**
+ * Add a new effect to the transit.
+ *
+ * @note The cb function and the data are the key to the effect. If you try to
+ * add an already added effect, nothing is done.
+ * @note After the first addition of an effect in @p transit, if its
+ * effect list become empty again, the @p transit will be killed by
+ * elm_transit_del(transit) function.
+ *
+ * Exemple:
+ * @code
+ * Elm_Transit *transit = elm_transit_add();
+ * elm_transit_effect_add(transit,
+ *                        elm_transit_effect_blend_op,
+ *                        elm_transit_effect_blend_context_new(),
+ *                        elm_transit_effect_blend_context_free);
+ * @endcode
+ *
+ * @param transit The transit object.
+ * @param cb The operation function. It is called when the animation begins,
+ * it is the function that actually performs the animation. It is called with
+ * the @p data, @p transit and the time progression of the animation (a double
+ * value between 0.0 and 1.0).
+ * @param data The context data of the effect.
+ * @param data_free_cb The function to free the context data, it will be called
+ * at the end of the effect, it must finalize the animation and free the
+ * @p data.
+ *
+ * @ingroup Transit
+ * @warning The transit free the context data at the and of the transition with
+ * the data_free_cb function, do not use the context data in another transit.
+ */
+EAPI void
+elm_transit_effect_add(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit *transit, double progress), void *data, void (*data_free_cb)(void *data, Elm_Transit *transit))
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(cb);
+   Elm_Transit_Effect *effect;
+   Eina_List *elist;
+
+   EINA_LIST_FOREACH(transit->effect_list, elist, effect)
+     {
+        if ((effect->animation_op == cb) && (effect->user_data == data)) return;
+     }
+
+   effect = ELM_NEW(Elm_Transit_Effect);
+   if (!effect) return;
+   
+   effect->user_data_free = data_free_cb;
+   effect->animation_op = cb;
+   effect->user_data = data;
+
+   transit->effect_list = eina_list_append(transit->effect_list, effect);
+}
+
+/**
+ * Delete an added effect.
+ *
+ * This function will remove the effect from the @p transit, calling the
+ * data_free_cb to free the @p data.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @note If the effect is not found, nothing is done.
+ * @note If the effect list become empty, this function will call
+ * elm_transit_del(transit), that is, it will kill the @p transit.
+ *
+ * @param transit The transit object.
+ * @param cb The operation function.
+ * @param data The context data of the effect.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_effect_del(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit *transit, double progress), void *data)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(cb);
+   Eina_List *elist, *elist_next;
+   Elm_Transit_Effect *effect;
+
+   EINA_LIST_FOREACH_SAFE(transit->effect_list, elist, elist_next, effect)
+     {
+        if ((effect->animation_op == cb) && (effect->user_data == data))
+          {
+             if (transit->walking)
+               {
+                  effect->deleted = EINA_TRUE;
+                  transit->effects_pending_del++;
+               }
+             else
+               {
+                  _elm_transit_effect_del(transit, effect, elist);
+                  if (!transit->effect_list) elm_transit_del(transit);
+               }
+             return;
+          }
+     }
+}
+
+/**
+ * Add new object to apply the effects.
+ *
+ * @note After the first addition of an object in @p transit, if its
+ * object list become empty again, the @p transit will be killed by
+ * elm_transit_del(transit) function.
+ * @note If the @p obj belongs to another transit, the @p obj will be
+ * removed from it and it will only belong to the @p transit. If the old
+ * transit stays without objects, it will die.
+ * @note When you add an object into the @p transit, its state from
+ * evas_object_pass_events_get(obj) is saved, and it is applied when the
+ * transit ends, if you change this state whith evas_object_pass_events_set()
+ * after add the object, this state will change again when @p transit stops to
+ * run.
+ *
+ * @param transit The transit object.
+ * @param obj Object to be animated.
+ *
+ * @ingroup Transit
+ * @warning See the documentation of the effect if is safe add or remove
+ * an object after @p transit begins to run.
+ */
+EAPI void
+elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   Elm_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
+
+   if (obj_data)
+     {
+        if (obj_data->transit == transit) return;
+        elm_transit_object_remove(obj_data->transit, obj);
+     }
+   
+   obj_data = ELM_NEW(Elm_Obj_Data);
+   obj_data->state = evas_object_pass_events_get(obj);
+   obj_data->transit = transit;
+   evas_object_data_set(obj, _transit_key, obj_data);
+   
+   transit->objs = eina_list_append(transit->objs, obj);
+   
+   if (!transit->event_enabled) 
+      evas_object_pass_events_set(obj, EINA_TRUE);
+   
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                  _elm_transit_object_remove_cb, transit);
+}
+
+/**
+ * Removes an added object from the transit.
+ *
+ * @note If the @p obj is not in the @p transit, nothing is done.
+ * @note If the list become empty, this function will call
+ * elm_transit_del(transit), that is, it will kill the @p transit.
+ *
+ * @param transit The transit object.
+ * @param obj Object to be removed from @p transit.
+ *
+ * @ingroup Transit
+ * @warning See the documentation of the effect if is safe add or remove
+ * an object after @p transit begins to run.
+ */
+EAPI void
+elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   Elm_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
+   if ((!obj_data) || (obj_data->transit != transit)) return;
+
+   _elm_transit_object_remove(transit, obj);
+   if (!transit->objs) elm_transit_del(transit);
+}
+
+/**
+ * Get the objects of the transit.
+ *
+ * @param transit The transit object.
+ * @return a Eina_List with the objects from the transit.
+ *
+ * @ingroup Transit
+ */
+EAPI const Eina_List *
+elm_transit_objects_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   return transit->objs;
+}
+
+/**
+ * Set the event enabled when transit is operating.
+ *
+ * If @p enabled is EINA_TRUE, the objects of the transit will receives
+ * events from mouse and keyboard during the animation.
+ * @note When you add an object with elm_transit_object_add(), its state from
+ * evas_object_pass_events_get(obj) is saved, and it is applied when the
+ * transit ends, if you change this state with evas_object_pass_events_set()
+ * after add the object, this state will change again when @p transit stops to
+ * run.
+ *
+ * @param transit The transit object.
+ * @param enabled Disable or enable.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   Evas_Object *obj;
+   Eina_List *elist;
+   Elm_Obj_Data *obj_data;
+
+   if (transit->event_enabled == enabled) return;
+
+   transit->event_enabled = enabled;
+
+   if (enabled)
+     {
+        EINA_LIST_FOREACH(transit->objs, elist, obj)
+          {
+             obj_data = evas_object_data_get(obj, _transit_key);
+             evas_object_pass_events_set(obj, obj_data->state);
+          }
+     }
+   else
+     {
+        EINA_LIST_FOREACH(transit->objs, elist, obj)
+           evas_object_pass_events_set(obj, EINA_TRUE);
+     }
+}
+
+/**
+ * Get the value of event enabled status.
+ *
+ * @see elm_transit_event_enabled_set()
+ *
+ * @param transit The Transit object
+ * @return EINA_TRUE, when event is enabled. If @p transit is NULL
+ * EINA_FALSE is returned
+ *
+ * @ingroup Transit
+ */
+EAPI Eina_Bool
+elm_transit_event_enabled_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
+
+   return transit->event_enabled;
+}
+
+
+/**
+ * Set the event enabled when transit is operating.
+ *
+ * If @p disabled is EINA_TRUE, the objects of the transit will receives
+ * events from mouse and keyboard during the animation.
+ * @note When you add an object with elm_transit_object_add(), its state from
+ * evas_object_pass_events_get(obj) is saved, and it is applied when the
+ * transit ends, if you change this state with evas_object_pass_events_set()
+ * after add the object, this state will change again when @p transit stops to
+ * run.
+ *
+ * @see elm_transit_event_enabled_set()
+ *
+ * @param transit The transit object.
+ * @param disabled Disable or enable.
+ *
+ * @ingroup Transit
+ */
+EINA_DEPRECATED EAPI void
+elm_transit_event_block_set(Elm_Transit *transit, Eina_Bool disabled)
+{
+   elm_transit_event_enabled_set(transit, disabled);
+}
+
+
+/**
+ * Get the value of event block enabled  status.
+ *
+ * @see elm_transit_event_enabled_set(), elm_transit_event_enabled_get()
+ *
+ * @param transit The Transit object
+ * @return EINA_TRUE, when event is enabled. If @p transit is NULL
+ * EINA_FALSE is returned
+ *
+ * @ingroup Transit
+ */
+EINA_DEPRECATED EAPI Eina_Bool
+elm_transit_event_block_get(const Elm_Transit *transit)
+{
+   return !elm_transit_event_enabled_get(transit);
+}
+
+/**
+ * Set the user-callback function when the transit is deleted.
+ *
+ * @note Using this function twice will overwrite the first function setted.
+ * @note the @p transit object will be deleted after call @p cb function.
+ *
+ * @param transit The transit object.
+ * @param cb Callback function pointer. This function will be called before
+ * the deletion of the transit.
+ * @param data Callback funtion user data. It is the @p op parameter.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_del_cb_set(Elm_Transit *transit, void (*cb) (void *data, Elm_Transit *transit), void *data)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   transit->del_data.func = cb;
+   transit->del_data.arg = data;
+}
+
+/**
+ * Set reverse effect automatically.
+ *
+ * If auto reverse is setted, after running the effects with the progress
+ * parameter from 0 to 1, it will call the effecs again with the progress
+ * from 1 to 0. The transit will last for a time iqual to (2 * duration * repeat),
+ * where the duration was setted with the function elm_transit_add and
+ * the repeat with the function elm_transit_repeat_times_set().
+ *
+ * @param transit The transit object.
+ * @param reverse EINA_TRUE means the auto_reverse is on.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   transit->auto_reverse = reverse;
+}
+
+/**
+ * Get if the auto reverse is on.
+ *
+ * @see elm_transit_auto_reverse_set()
+ *
+ * @param transit The transit object.
+ * @return EINA_TRUE means auto reverse is on. If @p transit is NULL
+ * EINA_FALSE is returned
+ *
+ * @ingroup Transit
+ */
+EAPI Eina_Bool
+elm_transit_auto_reverse_get(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
+   return transit->auto_reverse;
+}
+
+/**
+ * Set the transit repeat count. Effect will be repeated by repeat count.
+ *
+ * This function sets the number of repetition the transit will run after
+ * the first one, that is, if @p repeat is 1, the transit will run 2 times.
+ * If the @p repeat is a negative number, it will repeat infinite times.
+ *
+ * @note If this function is called during the transit execution, the transit
+ * will run @p repeat times, ignoring the times it already performed.
+ *
+ * @param transit The transit object
+ * @param repeat Repeat count
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_repeat_times_set(Elm_Transit *transit, int repeat)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   transit->repeat.count = repeat;
+   transit->repeat.current = 0;
+}
+
+/**
+ * Get the transit repeat count.
+ *
+ * @see elm_transit_repeat_times_set()
+ *
+ * @param transit The Transit object.
+ * @return The repeat count. If @p transit is NULL
+ * 0 is returned
+ *
+ * @ingroup Transit
+ */
+EAPI int
+elm_transit_repeat_times_get(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
+   return transit->repeat.count;
+}
+
+/**
+ * Set the transit animation acceleration type.
+ *
+ * This function sets the tween mode of the transit that can be:
+ * ELM_TRANSIT_TWEEN_MODE_LINEAR - The default mode.
+ * ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL - Starts in accelerate mode and ends decelerating.
+ * ELM_TRANSIT_TWEEN_MODE_DECELERATE - The animation will be slowed over time.
+ * ELM_TRANSIT_TWEEN_MODE_ACCELERATE - The animation will accelerate over time.
+ *
+ * @param transit The transit object.
+ * @param tween_mode The tween type.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+
+   transit->tween_mode = tween_mode;
+}
+
+/**
+ * Get the transit animation acceleration type.
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ * @return The tween type. If @p transit is NULL
+ * ELM_TRANSIT_TWEEN_MODE_LINEAR is returned.
+ *
+ * @ingroup Transit
+ */
+EAPI Elm_Transit_Tween_Mode
+elm_transit_tween_mode_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
+   return transit->tween_mode;
+}
+
+/**
+ * Set the transit animation time
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ * @param duration The animation time.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_duration_set(Elm_Transit *transit, double duration)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   if (transit->animator) return;
+   transit->time.duration = duration;
+}
+
+/**
+ * Get the transit animation time
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ *
+ * @return The transit animation time.
+ *
+ * @ingroup Transit
+ */
+EAPI double 
+elm_transit_duration_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, 0.0);
+   return transit->time.duration;
+}
+
+/**
+ * Starts the transition. 
+ * Once this API is called, the transit begins to measure the time.
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_go(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+
+   if (transit->animator)
+      ecore_animator_del(transit->animator);
+
+   transit->time.paused = 0;
+   transit->time.delayed = 0;
+   transit->time.begin = ecore_loop_time_get();
+   transit->animator = ecore_animator_add(_animator_animate_cb, transit);
+}
+
+/**
+ * Pause/Resume the transition. 
+ * If you call elm_transit_go again, paused states will affect no anymore. 
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+
+   if (!transit->animator) return;
+
+   if (paused)
+     {
+        if (transit->time.paused > 0) 
+           return;
+        ecore_animator_freeze(transit->animator);
+        transit->time.paused = ecore_loop_time_get();
+     }
+   else
+     {
+        if (transit->time.paused == 0) 
+           return;
+        ecore_animator_thaw(transit->animator);
+        transit->time.delayed += (ecore_loop_time_get() - transit->time.paused);
+        transit->time.paused = 0;
+     }
+}
+
+/**
+ * Get the value of paused status. 
+ *
+ * @see elm_transit_paused_set()
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ * @return EINA_TRUE means transition is paused. If @p transit is NULL
+ * EINA_FALSE is returned
+ *
+ * @ingroup Transit
+ */
+EAPI Eina_Bool
+elm_transit_paused_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
+
+   if (transit->time.paused == 0) 
+      return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+/**
+ * Get the time progression of the animation (a double value between 0.0 and 1.0).
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ *
+ * @return The time progression value. If @p transit is NULL
+ * 0 is returned
+ *
+ * @ingroup Transit
+ */
+EAPI double
+elm_transit_progress_value_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
+
+   return transit->progress;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//Resizing FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Resizing Elm_Transit_Effect_Resizing;
+
+struct _Elm_Transit_Effect_Resizing
+{
+   struct _size {
+      Evas_Coord w, h;
+   } from, to;
+};
+
+static void
+_transit_effect_resizing_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_transit_effect_resizing_op(void *data, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Coord w, h;
+   Evas_Object *obj;
+   Eina_List *elist;
+   Elm_Transit_Effect_Resizing *resizing = data;
+
+   w = resizing->from.w + (resizing->to.w * progress);
+   h = resizing->from.h + (resizing->to.h * progress);
+   
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+      evas_object_resize(obj, w, h);
+}
+
+static void *
+_transit_effect_resizing_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
+{
+   Elm_Transit_Effect_Resizing *resizing;
+
+   resizing = ELM_NEW(Elm_Transit_Effect_Resizing);
+   if (!resizing) return NULL;
+
+   resizing->from.w = from_w;
+   resizing->from.h = from_h;
+   resizing->to.w = to_w - from_w;
+   resizing->to.h = to_h - from_h;
+
+   return resizing;
+}
+
+/**
+ * Add the Resizing Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates resizing effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect will be applied to the objects that are in the transit,
+ * @note If you change the set of objects in the transit with  elm_transit_object_add()
+ * or elm_transit_object_remove(), the set of objects affected by this effect
+ * will be changed too.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_w Object width size when effect begins.
+ * @param from_h Object height size when effect begins.
+ * @param to_w Object width size when effect ends.
+ * @param to_h Object height size when effect ends.
+ * @return Resizing effect context data.
+ *
+ * @ingroup Transit
+*/
+EAPI void *
+elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_resizing_context_new(from_w, from_h, to_w, to_h);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_resizing_op, effect_context,
+                          _transit_effect_resizing_context_free);
+   return effect_context;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//Translation FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Translation Elm_Transit_Effect_Translation;
+typedef struct _Elm_Transit_Effect_Translation_Node Elm_Transit_Effect_Translation_Node;
+
+struct _Elm_Transit_Effect_Translation_Node
+{
+   Evas_Object *obj;
+   Evas_Coord x, y;
+};
+
+struct _Elm_Transit_Effect_Translation
+{
+   struct _position_variation {
+      Evas_Coord dx, dy;
+   } from, to;
+   Eina_List *nodes;
+};
+
+static void
+_translation_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit_Effect_Translation *translation = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_Translation_Node *translation_node;
+   
+   EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
+     {
+        if (translation_node->obj != obj) continue;
+        translation->nodes = eina_list_remove_list(translation->nodes, elist);
+        free(translation_node);
+        break;
+     }
+}
+
+static Eina_List *
+_translation_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Translation *translation)
+{
+   Elm_Transit_Effect_Translation_Node *translation_node;
+   const Eina_List *elist;
+   Evas_Object *obj;
+   Eina_List *data_list = NULL;
+   const Eina_List *objs = elm_transit_objects_get(transit);
+   
+   EINA_LIST_FOREACH(objs, elist, obj)
+     {
+        translation_node = ELM_NEW(Elm_Transit_Effect_Translation_Node);
+        if (!translation_node)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+        translation_node->obj = obj;
+        evas_object_geometry_get(obj, &(translation_node->x),
+                                 &(translation_node->y), NULL, NULL);
+        data_list = eina_list_append(data_list, translation_node);
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                       _translation_object_del_cb, translation);
+     }
+   return data_list;
+}
+
+void
+_transit_effect_translation_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   Elm_Transit_Effect_Translation *translation = data;
+   Eina_List *elist, *elist_next;
+   Elm_Transit_Effect_Translation_Node *translation_node;
+
+   EINA_LIST_FOREACH_SAFE(translation->nodes,
+                          elist, elist_next, translation_node)
+     {
+        evas_object_event_callback_del(translation_node->obj,
+                                       EVAS_CALLBACK_DEL, _translation_object_del_cb);
+        translation->nodes = eina_list_remove_list(translation->nodes, elist);
+        free(translation_node);
+     }
+   free(translation);
+}
+
+void
+_transit_effect_translation_op(void *data, Elm_Transit *transit, double progress __UNUSED__)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Coord x, y;
+   Elm_Transit_Effect_Translation *translation = data;
+   Elm_Transit_Effect_Translation_Node *translation_node;
+   Eina_List *elist;
+   
+   if (!translation->nodes)
+      translation->nodes = _translation_nodes_build(transit, translation);
+   
+   EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
+     {
+        x = translation_node->x + translation->from.dx
+           + (translation->to.dx * progress);
+        y = translation_node->y + translation->from.dy
+           + (translation->to.dy * progress);
+        evas_object_move(translation_node->obj, x, y);
+     }
+}
+
+static void *
+_transit_effect_translation_context_new(Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
+{
+   Elm_Transit_Effect_Translation *translation;
+
+   translation = ELM_NEW(Elm_Transit_Effect_Translation);
+   if (!translation) return NULL;
+
+   translation->from.dx = from_dx;
+   translation->from.dy = from_dy;
+   translation->to.dx = to_dx - from_dx;
+   translation->to.dy = to_dy - from_dy;
+
+   return translation;
+}
+
+/**
+ * Add the Translation Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates translation effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note When this function is called, it gets the current objects in
+ * the transit, that is, elm_transit_object_remove() and elm_transit_object_add()
+ * will not cause any changes in the set of objects that this effect is being
+ * applied.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_dx X Position variation when effect begins.
+ * @param from_dy Y Position variation when effect begins.
+ * @param to_dx X Position variation when effect ends.
+ * @param to_dy Y Position variation when effect ends.
+ * @return Translation effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_translation_context_new(from_dx, from_dy, to_dx, to_dy);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_translation_op, effect_context,
+                          _transit_effect_translation_context_free);
+   return effect_context;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Zoom FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Zoom Elm_Transit_Effect_Zoom;
+
+struct _Elm_Transit_Effect_Zoom
+{
+   float from, to;
+};
+
+void
+_transit_effect_zoom_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_transit_effect_zoom_op(void *data, Elm_Transit *transit , double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Object *obj;
+   Eina_List *elist;
+   Elm_Transit_Effect_Zoom *zoom = data;
+   Evas_Map *map;
+   Evas_Coord x, y, w, h;
+
+   map = evas_map_new(4);
+   if (!map) return;
+
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        evas_object_geometry_get(obj, &x, &y, &w, &h);
+        evas_map_smooth_set(map, EINA_TRUE);
+        evas_map_util_points_populate_from_object_full(map, obj, zoom->from +
+                                                       (progress * zoom->to));
+        evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, FOCAL);
+        evas_object_map_set(obj, map);
+        evas_object_map_enable_set(obj, EINA_TRUE);
+     }
+   evas_map_free(map);
+}
+
+static void *
+_transit_effect_zoom_context_new(float from_rate, float to_rate)
+{
+   Elm_Transit_Effect_Zoom *zoom;
+
+   zoom = ELM_NEW(Elm_Transit_Effect_Zoom);
+   if (!zoom) return NULL;
+
+   zoom->from = (FOCAL - (from_rate * FOCAL)) * (1 / from_rate);
+   zoom->to = ((FOCAL - (to_rate * FOCAL)) * (1 / to_rate)) - zoom->from;
+
+   return zoom;
+}
+
+/**
+ * Add the Zoom Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates zoom effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note If you change the set of objects in the transit with  elm_transit_object_add()
+ * or elm_transit_object_remove(), the set of objects affected by this effect
+ * will be changed too.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_rate Scale rate when effect begins (1 is current rate).
+ * @param to_rate Scale rate when effect ends.
+ * @return Zoom effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_zoom_context_new(from_rate, to_rate);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_zoom_op, effect_context,
+                          _transit_effect_zoom_context_free);
+   return effect_context;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Flip FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Flip Elm_Transit_Effect_Flip;
+
+struct _Elm_Transit_Effect_Flip
+{
+   Elm_Transit_Effect_Flip_Axis axis;
+   Eina_Bool cw : 1;
+};
+
+static void
+_transit_effect_flip_context_free(void *data, Elm_Transit *transit)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Object *front, *back;
+   int i;
+   int count = eina_list_count(transit->objs);
+   
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        front = eina_list_nth(transit->objs, i);
+        back = eina_list_nth(transit->objs, i+1);
+        evas_object_map_enable_set(front, EINA_FALSE);
+        evas_object_map_enable_set(back, EINA_FALSE);
+     }
+   free(data);
+}
+
+static void
+_transit_effect_flip_op(void *data, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Object *obj, *front, *back;
+   int count, i;
+   Elm_Transit_Effect_Flip *flip = data;
+   Evas_Map *map;
+   float degree;
+   Evas_Coord x, y, w, h;
+
+   map = evas_map_new(4);
+   if (!map) return;
+
+   if (flip->cw) degree = (float)(progress * 180);
+   else degree = (float)(progress * -180);
+   
+   count = eina_list_count(transit->objs);
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        Evas_Coord half_w, half_h;
+        
+        front = eina_list_nth(transit->objs, i);
+        back = eina_list_nth(transit->objs, i+1);
+        
+        if ((degree < 90) && (degree > -90))
+          {
+             obj = front;
+             if (front != back) 
+               {
+                  evas_object_hide(back);
+                  evas_object_show(front);
+               }
+          }
+        else
+          {
+             obj = back;
+             if (front != back)
+               {
+                  evas_object_hide(front);
+                  evas_object_show(back);
+               }
+          }
+        
+        evas_map_smooth_set(map, EINA_TRUE);
+        evas_map_util_points_populate_from_object_full(map, obj, 0);
+        evas_object_geometry_get(obj, &x, &y, &w, &h);
+        half_w = (w / 2);
+        half_h = (h / 2);
+        
+        if (flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
+          {
+             if ((degree >= 90) || (degree <= -90))
+               {
+                  evas_map_point_image_uv_set(map, 0, w, 0);
+                  evas_map_point_image_uv_set(map, 1, 0, 0);
+                  evas_map_point_image_uv_set(map, 2, 0, h);
+                  evas_map_point_image_uv_set(map, 3, w, h);
+               }
+             evas_map_util_3d_rotate(map, 0, degree,
+                                     0, x + half_w, y + half_h, 0);
+          }
+        else
+          {
+             if ((degree >= 90) || (degree <= -90))
+               {
+                  evas_map_point_image_uv_set(map, 0, 0, h);
+                  evas_map_point_image_uv_set(map, 1, w, h);
+                  evas_map_point_image_uv_set(map, 2, w, 0);
+                  evas_map_point_image_uv_set(map, 3, 0, 0);
+               }
+             evas_map_util_3d_rotate(map, degree,
+                                     0, 0, x + half_w, y + half_h, 0);
+          }
+        evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, FOCAL);
+        evas_object_map_enable_set(front, EINA_TRUE);
+        evas_object_map_enable_set(back, EINA_TRUE);
+        evas_object_map_set(obj, map);
+     }
+   evas_map_free(map);
+}
+
+static void *
+_transit_effect_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
+{
+   Elm_Transit_Effect_Flip *flip;
+
+   flip = ELM_NEW(Elm_Transit_Effect_Flip);
+   if (!flip) return NULL;
+
+   flip->cw = cw;
+   flip->axis = axis;
+
+   return flip;
+}
+
+/**
+ * Add the Flip Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates flip effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "front" object and the second will be the "back" object.
+ * @note If you change the set of objects in the transit with  elm_transit_object_add()
+ * or elm_transit_object_remove(), the set of objects affected by this effect
+ * will be changed too.
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param axis Flipping Axis(X or Y).
+ * @param cw Flipping Direction. EINA_TRUE is clock-wise.
+ * @return Flip effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_flip_context_new(axis, cw);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_flip_op, effect_context,
+                          _transit_effect_flip_context_free);
+   return effect_context;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//ResizableFlip FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Resizable_Flip Elm_Transit_Effect_ResizableFlip;
+typedef struct _Elm_Transit_Effect_Resizable_Flip_Node Elm_Transit_Effect_ResizableFlip_Node;
+
+struct _Elm_Transit_Effect_Resizable_Flip_Node
+{
+   Evas_Object *front;
+   Evas_Object *back;
+   struct _vector2d {
+      float x, y;
+   } from_pos, from_size, to_pos, to_size;
+};
+
+struct _Elm_Transit_Effect_Resizable_Flip
+{
+   Eina_List *nodes;
+   Eina_Bool cw : 1;
+   Elm_Transit_Effect_Flip_Axis axis;
+};
+
+static void
+_resizable_flip_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
+
+   EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
+     {
+        if (resizable_flip_node->front == obj)
+          evas_object_event_callback_del(resizable_flip_node->back,
+                             EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        else if (resizable_flip_node->back == obj)
+          evas_object_event_callback_del(resizable_flip_node->front,
+                             EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        else continue;
+
+        resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
+                                                      elist);
+        free(resizable_flip_node);
+        break;
+     }
+}
+
+static Eina_List *
+_resizable_flip_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_ResizableFlip *resizable_flip)
+{
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
+   Eina_List *data_list = NULL;
+   Evas_Coord front_x, front_y, front_w, front_h;
+   Evas_Coord back_x, back_y, back_w, back_h;
+   int i, count;
+
+   count = eina_list_count(transit->objs);
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        resizable_flip_node = ELM_NEW(Elm_Transit_Effect_ResizableFlip_Node);
+        if (!resizable_flip_node)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+        
+        resizable_flip_node->front = eina_list_nth(transit->objs, i);
+        resizable_flip_node->back = eina_list_nth(transit->objs, i+1);
+        
+        evas_object_geometry_get(resizable_flip_node->front,
+                                 &front_x, &front_y, &front_w, &front_h);
+        evas_object_geometry_get(resizable_flip_node->back,
+                                 &back_x, &back_y, &back_w, &back_h);
+        
+        resizable_flip_node->from_pos.x = front_x;
+        resizable_flip_node->from_pos.y = front_y;
+        resizable_flip_node->to_pos.x = back_x - front_x;
+        resizable_flip_node->to_pos.y = back_y - front_y;
+        
+        resizable_flip_node->from_size.x = front_w;
+        resizable_flip_node->from_size.y = front_h;
+        resizable_flip_node->to_size.x = back_w - front_w;
+        resizable_flip_node->to_size.y = back_h - front_h;
+        
+        data_list = eina_list_append(data_list, resizable_flip_node);
+        
+        evas_object_event_callback_add(resizable_flip_node->back,
+                                       EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
+        evas_object_event_callback_add(resizable_flip_node->front,
+                                       EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
+     }
+   
+   return data_list;
+}
+
+static void
+_set_image_uv_by_axis_y(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
+{
+   if ((degree >= 90) || (degree <= -90))
+     {
+        evas_map_point_image_uv_set(map, 0,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    0);
+        evas_map_point_image_uv_set(map, 1, 0, 0);
+        evas_map_point_image_uv_set(map, 2, 0,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
+        evas_map_point_image_uv_set(map, 3,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
+     }
+   else
+     {
+        evas_map_point_image_uv_set(map, 0, 0, 0);
+        evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
+        evas_map_point_image_uv_set(map, 2, flip->from_size.x,
+                                    flip->from_size.y);
+        evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
+     }
+}
+
+static void
+_set_image_uv_by_axis_x(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
+{
+   if ((degree >= 90) || (degree <= -90))
+     {
+        evas_map_point_image_uv_set(map, 0, 0,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
+        evas_map_point_image_uv_set(map, 1,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
+        evas_map_point_image_uv_set(map, 2,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    0);
+        evas_map_point_image_uv_set(map, 3, 0, 0);
+     }
+   else
+     {
+        evas_map_point_image_uv_set(map, 0, 0, 0);
+        evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
+        evas_map_point_image_uv_set(map, 2, flip->from_size.x,
+                                    flip->from_size.y);
+        evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
+     }
+}
+
+void
+_transit_effect_resizable_flip_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+
+   Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
+   Eina_List *elist, *elist_next;
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
+
+   EINA_LIST_FOREACH_SAFE(resizable_flip->nodes,
+                          elist, elist_next, resizable_flip_node)
+     {
+        evas_object_map_enable_set(resizable_flip_node->front, EINA_FALSE);
+        evas_object_map_enable_set(resizable_flip_node->back, EINA_FALSE);
+
+        resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
+                                                      elist);
+
+        evas_object_event_callback_del(resizable_flip_node->back,
+                             EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        evas_object_event_callback_del(resizable_flip_node->front,
+                             EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        free(resizable_flip_node);
+     }
+   free(resizable_flip);
+}
+
+void
+_transit_effect_resizable_flip_op(void *data, Elm_Transit *transit __UNUSED__, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   Evas_Map *map;
+   Evas_Object *obj;
+   float x, y, w, h;
+   float degree;
+   Evas_Coord half_w, half_h;
+   Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
+   Eina_List *elist;
+
+   map = evas_map_new(4);
+   if (!map) return;
+
+   if (resizable_flip->cw) degree = (float)(progress * 180);
+   else degree = (float)(progress * -180);
+   
+   if (!resizable_flip->nodes)
+      resizable_flip->nodes = _resizable_flip_nodes_build(transit,
+                                                          resizable_flip);
+   
+   EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
+     {
+        if ((degree < 90) && (degree > -90))
+          {
+             obj = resizable_flip_node->front;
+             if (resizable_flip_node->front != resizable_flip_node->back)
+               {
+                  evas_object_hide(resizable_flip_node->back);
+                  evas_object_show(resizable_flip_node->front);
+               }
+          }
+        else
+          {
+             obj = resizable_flip_node->back;
+             if (resizable_flip_node->front != resizable_flip_node->back)
+               {
+                  evas_object_hide(resizable_flip_node->front);
+                  evas_object_show(resizable_flip_node->back);
+               }
+          }
+        
+        evas_map_smooth_set(map, EINA_TRUE);
+        
+        x = resizable_flip_node->from_pos.x +
+           (resizable_flip_node->to_pos.x * progress);
+        y = resizable_flip_node->from_pos.y +
+           (resizable_flip_node->to_pos.y * progress);
+        w = resizable_flip_node->from_size.x +
+           (resizable_flip_node->to_size.x * progress);
+        h = resizable_flip_node->from_size.y +
+           (resizable_flip_node->to_size.y * progress);
+        evas_map_point_coord_set(map, 0, x, y, 0);
+        evas_map_point_coord_set(map, 1, x + w, y, 0);
+        evas_map_point_coord_set(map, 2, x + w, y + h, 0);
+        evas_map_point_coord_set(map, 3, x, y + h, 0);
+        
+        half_w = (Evas_Coord)(w / 2);
+        half_h = (Evas_Coord)(h / 2);
+        
+        if (resizable_flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
+          {
+             _set_image_uv_by_axis_y(map, resizable_flip_node, degree);
+             evas_map_util_3d_rotate(map, 0, degree,
+                                     0, x + half_w, y + half_h, 0);
+          }
+        else
+          {
+             _set_image_uv_by_axis_x(map, resizable_flip_node, degree);
+             evas_map_util_3d_rotate(map, degree, 0,
+                                     0, x + half_w, y + half_h, 0);
+          }
+        
+        evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, FOCAL);
+        evas_object_map_enable_set(resizable_flip_node->front, EINA_TRUE);
+        evas_object_map_enable_set(resizable_flip_node->back, EINA_TRUE);
+        evas_object_map_set(obj, map);
+     }
+   evas_map_free(map);
+}
+
+static void *
+_transit_effect_resizable_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
+{
+   Elm_Transit_Effect_ResizableFlip *resizable_flip;
+   
+   resizable_flip = ELM_NEW(Elm_Transit_Effect_ResizableFlip);
+   if (!resizable_flip) return NULL;
+
+   resizable_flip->cw = cw;
+   resizable_flip->axis = axis;
+
+   return resizable_flip;
+}
+
+/**
+ * Add the Resizable Flip Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates resizable flip effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "front" object and the second will be the "back" object.
+ * @note When this function is called, it gets the current objects in
+ * the transit, that is, elm_transit_object_remove() and elm_transit_object_add()
+ * will not cause any changes in the set of objects that this effect is being
+ * applied.
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param axis Flipping Axis(X or Y).
+ * @param cw Flipping Direction. EINA_TRUE is clock-wise.
+ * @return Resizable flip effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_resizable_flip_context_new(axis, cw);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_resizable_flip_op, effect_context,
+                          _transit_effect_resizable_flip_context_free);
+   return effect_context;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Wipe FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Wipe Elm_Transit_Effect_Wipe;
+
+struct _Elm_Transit_Effect_Wipe
+{
+   Elm_Transit_Effect_Wipe_Type type;
+   Elm_Transit_Effect_Wipe_Dir dir;
+};
+
+static void
+_elm_fx_wipe_hide(Evas_Map * map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
+{
+   float w2, h2;
+
+   switch (dir)
+     {
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
+         w2 = w - (w * progress);
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w2, 0);
+         evas_map_point_image_uv_set(map, 2, w2, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, x + w2, y, 0);
+         evas_map_point_coord_set(map, 2, x + w2, h2, 0);
+         evas_map_point_coord_set(map, 3, x, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
+         w2 = (w * progress);
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, w2, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, w2, h);
+         evas_map_point_coord_set(map, 0, x + w2, y, 0);
+         evas_map_point_coord_set(map, 1, x + w, y, 0);
+         evas_map_point_coord_set(map, 2, x + w, h2, 0);
+         evas_map_point_coord_set(map, 3, x + w2, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
+         w2 = (x + w);
+         h2 = h - (h * progress);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h2);
+         evas_map_point_image_uv_set(map, 3, 0, h2);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, w2, y, 0);
+         evas_map_point_coord_set(map, 2, w2, y+h2, 0);
+         evas_map_point_coord_set(map, 3, x, y+h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
+         w2 = (x + w);
+         h2 = (h * progress);
+         evas_map_point_image_uv_set(map, 0, 0, h2);
+         evas_map_point_image_uv_set(map, 1, w, h2);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y + h2, 0);
+         evas_map_point_coord_set(map, 1, w2, y + h2, 0);
+         evas_map_point_coord_set(map, 2, w2, y + h, 0);
+         evas_map_point_coord_set(map, 3, x, y + h, 0);
+         break;
+      default:
+         break;
+     }
+   evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, FOCAL);
+}
+
+static void
+_elm_fx_wipe_show(Evas_Map *map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
+{
+   float w2, h2;
+
+   switch (dir)
+     {
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
+         w2 = (w - (w * progress));
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, w2, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, w2, h);
+         evas_map_point_coord_set(map, 0, x + w2, y, 0);
+         evas_map_point_coord_set(map, 1, w, y, 0);
+         evas_map_point_coord_set(map, 2, w, h2, 0);
+         evas_map_point_coord_set(map, 3, x + w2, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
+         w2 = (w * progress);
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w2, 0);
+         evas_map_point_image_uv_set(map, 2, w2, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, x + w2, y, 0);
+         evas_map_point_coord_set(map, 2, x + w2, h2, 0);
+         evas_map_point_coord_set(map, 3, x, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
+         w2 = (x + w);
+         h2 = (h - (h * progress));
+         evas_map_point_image_uv_set(map, 0, 0, h2);
+         evas_map_point_image_uv_set(map, 1, w, h2);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y + h2, 0);
+         evas_map_point_coord_set(map, 1, w2, y + h2, 0);
+         evas_map_point_coord_set(map, 2, w2, y + h, 0);
+         evas_map_point_coord_set(map, 3, x, y + h, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
+         w2 = (x + w);
+         h2 = (h * progress);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h2);
+         evas_map_point_image_uv_set(map, 3, 0, h2);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, w2, y, 0);
+         evas_map_point_coord_set(map, 2, w2, y + h2, 0);
+         evas_map_point_coord_set(map, 3, x, y + h2, 0);
+         break;
+      default:
+         break;
+     }
+   evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, FOCAL);
+}
+
+static void
+_transit_effect_wipe_context_free(void *data, Elm_Transit *transit)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Eina_List *elist;
+   Evas_Object *obj;
+   Elm_Transit_Effect_Wipe *wipe = data;
+   Eina_Bool reverse = elm_transit_auto_reverse_get(transit);
+
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        if ((wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW && !reverse)
+            || (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE && reverse))
+           evas_object_show(obj);
+        else evas_object_hide(obj);
+        evas_object_map_enable_set(obj, EINA_FALSE);
+     }
+
+   free(wipe);
+}
+
+static void
+_transit_effect_wipe_op(void *data, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Wipe *wipe = data;
+   Evas_Map *map;
+   Evas_Coord _x, _y, _w, _h;
+   Eina_List *elist;
+   Evas_Object *obj;
+
+   map = evas_map_new(4);
+   if (!map) return;
+   
+   evas_map_smooth_set(map, EINA_TRUE);
+   
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        evas_object_geometry_get(obj, &_x, &_y, &_w, &_h);
+        
+        if (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW)
+           _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)progress);
+        else
+           _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)progress);
+        
+        evas_object_map_enable_set(obj, EINA_TRUE);
+        evas_object_map_set(obj, map);
+     }
+   evas_map_free(map);
+}
+
+static void *
+_transit_effect_wipe_context_new(Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
+{
+   Elm_Transit_Effect_Wipe *wipe;
+   
+   wipe = ELM_NEW(Elm_Transit_Effect_Wipe);
+   if (!wipe) return NULL;
+
+   wipe->type = type;
+   wipe->dir = dir;
+
+   return wipe;
+}
+
+/**
+ * Add the Wipe Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates wipe effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect will be applied to the objects that are in the transit,
+ * If you change the set of objects in the transit with  elm_transit_object_add()
+ * or elm_transit_object_remove(), the set of objects affected by this effect
+ * will be changed too.
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param type Wipe type. Hide or show.
+ * @param dir Wipe Direction.
+ * @return Wipe effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_wipe_context_new(type, dir);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_wipe_op, effect_context,
+                          _transit_effect_wipe_context_free);
+   return effect_context;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Color FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Color Elm_Transit_Effect_Color;
+
+struct _Elm_Transit_Effect_Color
+{
+   struct _unsigned_color {
+      unsigned int r, g, b, a;
+   } from;
+   struct _signed_color {
+      int r, g, b, a;
+   } to;
+};
+
+static void
+_transit_effect_color_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_transit_effect_color_op(void *data, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Color *color = data;
+   Evas_Object *obj;
+   Eina_List *elist;
+   unsigned int r, g, b, a;
+   
+   r = (color->from.r + (int)((float)color->to.r * progress));
+   g = (color->from.g + (int)((float)color->to.g * progress));
+   b = (color->from.b + (int)((float)color->to.b * progress));
+   a = (color->from.a + (int)((float)color->to.a * progress));
+   
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+      evas_object_color_set(obj, r, g, b, a);
+}
+
+static void *
+_transit_effect_color_context_new(unsigned int from_r, unsigned int from_g, unsigned int from_b, unsigned int from_a, unsigned int to_r, unsigned int to_g, unsigned int to_b, unsigned int to_a)
+{
+   Elm_Transit_Effect_Color *color;
+   
+   color = ELM_NEW(Elm_Transit_Effect_Color);
+   if (!color) return NULL;
+   
+   color->from.r = from_r;
+   color->from.g = from_g;
+   color->from.b = from_b;
+   color->from.a = from_a;
+   color->to.r = to_r - from_r;
+   color->to.g = to_g - from_g;
+   color->to.b = to_b - from_b;
+   color->to.a = to_a - from_a;
+   
+   return color;
+}
+
+/**
+ * Add the Color Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates color effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect will be applied to the objects that are in the transit,
+ * If you change the set of objects in the transit with  elm_transit_object_add()
+ * or elm_transit_object_remove(), the set of objects affected by this effect
+ * will be changed too.
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit        Transit object.
+ * @param  from_r        RGB R when effect begins.
+ * @param  from_g        RGB G when effect begins.
+ * @param  from_b        RGB B when effect begins.
+ * @param  from_a        RGB A when effect begins.
+ * @param  to_r          RGB R when effect ends.
+ * @param  to_g          RGB G when effect ends.
+ * @param  to_b          RGB B when effect ends.
+ * @param  to_a          RGB A when effect ends.
+ * @return               Color effect context data.
+ *
+ * @ingroup Transit
+ */
+EAPI void *
+elm_transit_effect_color_add(Elm_Transit *transit, unsigned int from_r, unsigned int from_g, unsigned int from_b, unsigned int from_a, unsigned int to_r, unsigned int to_g, unsigned int to_b, unsigned int to_a)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_color_context_new(from_r, from_g, from_b, from_a, to_r, to_g, to_b, to_a);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_color_op, effect_context,
+                          _transit_effect_color_context_free);
+   return effect_context;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//Fade FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Fade Elm_Transit_Effect_Fade;
+typedef struct _Elm_Transit_Effect_Fade_Node Elm_Transit_Effect_Fade_Node;
+
+struct _Elm_Transit_Effect_Fade_Node
+{
+   Evas_Object *before;
+   Evas_Object *after;
+   struct _signed_color before_color, after_color;
+   int before_alpha;
+   int after_alpha;
+   Eina_Bool inversed : 1;
+};
+
+struct _Elm_Transit_Effect_Fade
+{
+   Eina_List *nodes;
+};
+
+static void
+_fade_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit_Effect_Fade *fade = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_Fade_Node *fade_node;
+
+   EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
+     {
+        if (fade_node->before == obj)
+           evas_object_event_callback_del(fade_node->after,
+                                          EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        else if (fade_node->after == obj)
+           evas_object_event_callback_del(fade_node->before,
+                                          EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        else continue;
+        
+        fade->nodes = eina_list_remove_list(fade->nodes, elist);
+        free(fade_node);
+        break;
+     }
+}
+
+static Eina_List *
+_fade_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Fade *fade_data)
+{
+   Elm_Transit_Effect_Fade_Node *fade;
+   Eina_List *data_list = NULL;
+   int i, count;
+
+   count = eina_list_count(transit->objs);
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        fade = ELM_NEW(Elm_Transit_Effect_Fade_Node);
+        if (!fade)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+        
+        fade->before = eina_list_nth(transit->objs, i);
+        fade->after = eina_list_nth(transit->objs, i+1);
+        
+        evas_object_color_get(fade->before,
+                              &fade->before_color.r, &fade->before_color.g,
+                              &fade->before_color.b, &fade->before_color.a);
+        evas_object_color_get(fade->after,
+                              &fade->after_color.r, &fade->after_color.g,
+                              &fade->after_color.b, &fade->after_color.a);
+        
+        fade->before_alpha = (255 - fade->before_color.a);
+        fade->after_alpha = (255 - fade->after_color.a);
+        
+        data_list = eina_list_append(data_list, fade);
+        
+        evas_object_event_callback_add(fade->before,
+                                       EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
+        evas_object_event_callback_add(fade->after,
+                                       EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
+     }
+   return data_list;
+}
+
+static void
+_transit_effect_fade_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   Elm_Transit_Effect_Fade *fade = data;
+   Elm_Transit_Effect_Fade_Node *fade_node;
+   Eina_List *elist, *elist_next;
+   
+   EINA_LIST_FOREACH_SAFE(fade->nodes, elist, elist_next, fade_node)
+     {
+        evas_object_color_set(fade_node->before, fade_node->before_color.r,
+                              fade_node->before_color.g,
+                              fade_node->before_color.b,
+                              fade_node->before_color.a);
+        evas_object_color_set(fade_node->after, fade_node->after_color.r,
+                              fade_node->after_color.g,
+                              fade_node->after_color.b,
+                              fade_node->after_color.a);
+
+        fade->nodes = eina_list_remove_list(fade->nodes, elist);
+        evas_object_event_callback_del(fade_node->before,
+                             EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        evas_object_event_callback_del(fade_node->after,
+                             EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        free(fade_node);
+     }
+
+   free(fade);
+}
+
+static void
+_transit_effect_fade_op(void *data, Elm_Transit *transit __UNUSED__, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   Elm_Transit_Effect_Fade *fade = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_Fade_Node *fade_node;
+   float _progress;
+   
+   if (!fade->nodes)
+      fade->nodes = _fade_nodes_build(transit, fade);
+   
+   EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
+     {
+        if (progress < 0.5)
+          {
+             if (!fade_node->inversed)
+               {
+                  evas_object_hide(fade_node->after);
+                  evas_object_show(fade_node->before);
+                  fade_node->inversed = EINA_TRUE;
+               }
+             
+             _progress = (1 - (progress * 2));
+             
+             evas_object_color_set(fade_node->before,
+                                   fade_node->before_color.r * _progress,
+                                   fade_node->before_color.g * _progress,
+                                   fade_node->before_color.b * _progress,
+                                   fade_node->before_color.a +
+                                   fade_node->before_alpha * (1 - _progress));
+          }
+        else
+          {
+             if (fade_node->inversed)
+               {
+                  evas_object_hide(fade_node->before);
+                  evas_object_show(fade_node->after);
+                  fade_node->inversed = EINA_FALSE;
+               }
+             
+             _progress = ((progress - 0.5) * 2);
+             
+             evas_object_color_set(fade_node->after,
+                                   fade_node->after_color.r * _progress,
+                                   fade_node->after_color.g * _progress,
+                                   fade_node->after_color.b * _progress,
+                                   fade_node->after_color.a +
+                                   fade_node->after_alpha * (1 - _progress));
+          }
+     }
+}
+
+static void *
+_transit_effect_fade_context_new(void)
+{
+   Elm_Transit_Effect_Fade *fade;
+   fade = ELM_NEW(Elm_Transit_Effect_Fade);
+   if (!fade) return NULL;
+   return fade;
+}
+
+/**
+ * Add the Fade Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates fade effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "before" object and the second will be the "after" object.
+ * @note When this function is called, it gets the current objects in
+ * the transit, that is, elm_transit_object_remove() and elm_transit_object_add()
+ * will not cause any changes in the set of objects that this effect is being
+ * applied.
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @return Fade effect context data.
+ * 
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the color information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_fade_add(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   
+   void *effect_context = _transit_effect_fade_context_new();
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_fade_op, effect_context,
+                          _transit_effect_fade_context_free);
+   return effect_context;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Blend FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Blend Elm_Transit_Effect_Blend;
+typedef struct _Elm_Transit_Effect_Blend_Node Elm_Transit_Effect_Blend_Node;
+
+struct _Elm_Transit_Effect_Blend_Node
+{
+   Evas_Object *before;
+   Evas_Object *after;
+   struct _signed_color from, to;
+};
+
+struct _Elm_Transit_Effect_Blend
+{
+   Eina_List *nodes;
+};
+
+static void
+_blend_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit_Effect_Blend *blend = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_Blend_Node *blend_node;
+   
+   EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
+     {
+        if (blend_node->after == obj)
+           evas_object_event_callback_del(blend_node->before,
+                                          EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        else if (blend_node->before == obj)
+           evas_object_event_callback_del(blend_node->after,
+                                          EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        else continue;
+        
+        blend->nodes = eina_list_remove_list(blend->nodes, elist);
+        free(blend_node);
+        break;
+     }
+}
+
+static Eina_List *
+_blend_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Blend *blend)
+{
+   Elm_Transit_Effect_Blend_Node *blend_node;
+   Eina_List *data_list = NULL;
+   int i, count;
+
+   count = eina_list_count(transit->objs);
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        blend_node = ELM_NEW(Elm_Transit_Effect_Blend_Node);
+        if (!blend_node)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+        
+        blend_node->before = eina_list_nth(transit->objs, i);
+        blend_node->after = eina_list_nth(transit->objs, i + 1);
+        evas_object_show(blend_node->before);
+        evas_object_show(blend_node->after);
+        
+        evas_object_color_get(blend_node->before, &blend_node->from.r,
+                              &blend_node->from.g, &blend_node->from.b,
+                              &blend_node->from.a);
+        evas_object_color_get(blend_node->after, &blend_node->to.r,
+                              &blend_node->to.g, &blend_node->to.b,
+                              &blend_node->to.a);
+        
+        data_list = eina_list_append(data_list, blend_node);
+        
+        evas_object_event_callback_add(blend_node->before,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
+        evas_object_event_callback_add(blend_node->after,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
+     }
+   return data_list;
+}
+
+void
+_transit_effect_blend_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   Elm_Transit_Effect_Blend *blend = data;
+   Elm_Transit_Effect_Blend_Node *blend_node;
+   Eina_List *elist, *elist_next;
+
+   EINA_LIST_FOREACH_SAFE(blend->nodes, elist, elist_next, blend_node)
+     {
+        evas_object_color_set(blend_node->before,
+                              blend_node->from.r, blend_node->from.g,
+                              blend_node->from.b, blend_node->from.a);
+        evas_object_color_set(blend_node->after, blend_node->to.r,
+                              blend_node->to.g, blend_node->to.b,
+                              blend_node->to.a);
+        
+        if (elm_transit_auto_reverse_get(transit))
+           evas_object_hide(blend_node->after);
+        else
+           evas_object_hide(blend_node->before);
+        
+        blend->nodes = eina_list_remove_list(blend->nodes, elist);
+        
+        evas_object_event_callback_del(blend_node->before,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        evas_object_event_callback_del(blend_node->after,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        free(blend_node);
+     }
+   free(data);
+}
+
+void
+_transit_effect_blend_op(void *data, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Blend *blend = data;
+   Elm_Transit_Effect_Blend_Node *blend_node;
+   Eina_List *elist;
+
+   if (!blend->nodes) blend->nodes = _blend_nodes_build(transit, blend);
+   
+   EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
+     {
+        evas_object_color_set(blend_node->before,
+                              (int)(blend_node->from.r * (1 - progress)),
+                              (int)(blend_node->from.g * (1 - progress)),
+                              (int)(blend_node->from.b * (1 - progress)),
+                              (int)(blend_node->from.a * (1 - progress)));
+        evas_object_color_set(blend_node->after,
+                              (int)(blend_node->to.r * progress),
+                              (int)(blend_node->to.g * progress),
+                              (int)(blend_node->to.b * progress),
+                              (int)(blend_node->to.a * progress));
+     }
+}
+
+static void *
+_transit_effect_blend_context_new(void)
+{
+   Elm_Transit_Effect_Blend *blend;
+   
+   blend = ELM_NEW(Elm_Transit_Effect_Blend);
+   if (!blend) return NULL;
+   return blend;
+}
+
+/**
+ * Add the Blend Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates blend effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "before" object and the second will be the "after" object.
+ * @note When this function be called, it gets the current objects in
+ * the transit, that is, elm_transit_object_remove() and elm_transit_object_add()
+ * will not cause any changes in the set of objects that this effect is being
+ * applied.
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @return Blend effect context data.
+ * 
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the color information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_blend_add(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_blend_context_new();
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_blend_op, effect_context,
+                          _transit_effect_blend_context_free);
+   return effect_context;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//Rotation FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Rotation Elm_Transit_Effect_Rotation;
+
+struct _Elm_Transit_Effect_Rotation
+{
+   float from, to;
+};
+
+static void
+_transit_effect_rotation_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   free(data);
+}
+
+static void
+_transit_effect_rotation_op(void *data, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Rotation *rotation = data;
+   Evas_Map *map;
+   Evas_Coord x, y, w, h;
+   float degree;
+   float half_w, half_h;
+   Eina_List *elist;
+   Evas_Object *obj;
+
+   map = evas_map_new(4);
+   if (!map) return;
+
+   evas_map_smooth_set(map, EINA_TRUE);
+
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        evas_map_util_points_populate_from_object_full(map, obj, 0);
+        degree = rotation->from + (float)(progress * rotation->to);
+
+        evas_object_geometry_get(obj, &x, &y, &w, &h);
+
+        half_w = (float)w * 0.5;
+        half_h = (float)h * 0.5;
+
+        evas_map_util_3d_rotate(map, 0, 0, degree, x + half_w, y + half_h, 0);
+        evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, FOCAL);
+        evas_object_map_enable_set(obj, EINA_TRUE);
+        evas_object_map_set(obj, map);
+     }
+   evas_map_free(map);
+}
+
+static void *
+_transit_effect_rotation_context_new(float from_degree, float to_degree)
+{
+   Elm_Transit_Effect_Rotation *rotation;
+
+   rotation = ELM_NEW(Elm_Transit_Effect_Rotation);
+   if (!rotation) return NULL;
+
+   rotation->from = from_degree;
+   rotation->to = to_degree - from_degree;
+
+   return rotation;
+}
+
+/**
+ * Add the Rotation Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates rotation effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * @note This effect will be applied to the objects that are in the transit,
+ * If you change the set of objects in the transit with  elm_transit_object_add()
+ * or elm_transit_object_remove(), the set of objects affected by this effect
+ * will be changed too.
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_degree Degree when effect begins.
+ * @param to_degree Degree when effect is ends.
+ * @return Rotation effect context data.
+ * 
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ * @warning Is not recommended remove or add an object after the transit begins
+ * to run, because the order of the objects will be affected.
+ */
+EAPI void *
+elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_rotation_context_new(from_degree, to_degree);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_rotation_op, effect_context,
+                          _transit_effect_rotation_context_free);
+   return effect_context;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// ImageAnimation FX
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Image_Animation Elm_Transit_Effect_Image_Animation;
+
+struct _Elm_Transit_Effect_Image_Animation
+{
+   Eina_List *images;
+};
+
+static void
+_transit_effect_image_animation_context_free(void *data, Elm_Transit *transit __UNUSED__)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   Elm_Transit_Effect_Image_Animation *image_animation = data;
+   const char *image;
+   Eina_List *elist, *elist_next;
+
+   EINA_LIST_FOREACH_SAFE(image_animation->images, elist, elist_next, image)
+     {
+        image_animation->images =
+           eina_list_remove_list(image_animation->images, elist);
+        eina_stringshare_del(image);
+     }
+
+   free(data);
+}
+
+static void
+_transit_effect_image_animation_op(void *data, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Eina_List *elist;
+   Evas_Object *obj;
+   const char *type;
+   Elm_Transit_Effect_Image_Animation *image_animation = data;
+   unsigned int count = 0;
+   int len;
+
+   type = eina_stringshare_add("icon");
+   len = eina_list_count(image_animation->images);
+   
+   if (!len) count = floor(progress * len);
+   else count = floor(progress * (len - 1));
+   
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        if (elm_widget_type_check(obj, type))
+           elm_icon_file_set(obj,
+                             eina_list_nth(image_animation->images, count), NULL);
+     }
+
+   eina_stringshare_del(type);
+}
+
+static void *
+_transit_effect_image_animation_context_new(Eina_List *images)
+{
+   Elm_Transit_Effect_Image_Animation *image_animation;
+   image_animation = ELM_NEW(Elm_Transit_Effect_Image_Animation);
+
+   if (!image_animation) return NULL;
+   image_animation->images = images;
+   return image_animation;
+}
+
+/**
+ * Add the Rotation Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates image animation effect context 
+ * and add it's required APIs to elm_transit_effect_add. 
+ * The @p images parameter is a list images paths. This list and
+ * its contents will be deleted at the end of the effect by
+ * elm_transit_effect_image_animation_context_free() function.
+ * @note This effect will be applied to the objects that are in the transit,
+ * If you change the set of objects in the transit with  elm_transit_object_add()
+ * or elm_transit_object_remove(), the set of objects affected by this effect
+ * will be changed too.
+ *
+ * Example:
+ * @code
+ * char buf[PATH_MAX];
+ * Eina_List *images = NULL;
+ * Elm_Transit *transi = elm_transit_add();
+ *
+ * snprintf(buf, sizeof(buf), "%s/images/icon_11.png", PACKAGE_DATA_DIR);
+ * images = eina_list_append(images, eina_stringshare_add(buf));
+ *
+ * snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+ * images = eina_list_append(images, eina_stringshare_add(buf));
+ * elm_transit_effect_image_animation_add(transi, images);
+ *
+ * @endcode
+ * 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param images Eina_List of images file paths. This list and
+ * its contents will be deleted at the end of the effect by
+ * elm_transit_effect_image_animation_context_free() function.
+ * @return Image Animation effect context data.
+ * 
+ * @ingroup Transit
+ */
+EAPI void *
+elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_image_animation_context_new(images);
+   
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit, 
+                          _transit_effect_image_animation_op, effect_context,
+                          _transit_effect_image_animation_context_free);
+   return effect_context;
+}
diff --git a/src/lib/elm_util.c b/src/lib/elm_util.c
new file mode 100644 (file)
index 0000000..f3d65d7
--- /dev/null
@@ -0,0 +1,197 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+#include "elm_priv.h"
+
+static char *
+_str_ncpy(char *dest, const char *src, size_t count)
+{
+   if ((!dest) || (!src)) return NULL;
+   return strncpy(dest, src, count);
+}
+
+static char *
+_str_append(char *str, const char *txt, int *len, int *alloc)
+{
+   int txt_len = strlen(txt);
+
+   if (txt_len <= 0) return str;
+   if ((*len + txt_len) >= *alloc)
+     {
+       char *str2;
+       int alloc2;
+
+       alloc2 = *alloc + txt_len + 128;
+       str2 = realloc(str, alloc2);
+       if (!str2) return str;
+       *alloc = alloc2;
+       str = str2;
+     }
+   strcpy(str + *len, txt);
+   *len += txt_len;
+   return str;
+}
+
+char *
+_elm_util_mkup_to_text(const char *mkup)
+{
+   char *str = NULL;
+   int str_len = 0, str_alloc = 0;
+   char *s, *p;
+   char *tag_start, *tag_end, *esc_start, *esc_end, *ts;
+
+   if (!mkup) return NULL;
+   tag_start = tag_end = esc_start = esc_end = NULL;
+   p = (char *)mkup;
+   s = p;
+   for (;;)
+     {
+       if ((!*p) ||
+           (tag_end) || (esc_end) ||
+           (tag_start) || (esc_start))
+         {
+            if (tag_end)
+              {
+                 char *ttag;
+
+                 ttag = malloc(tag_end - tag_start);
+                 if (ttag)
+                   {
+                      _str_ncpy(ttag, tag_start + 1, tag_end - tag_start - 1);
+                      ttag[tag_end - tag_start - 1] = 0;
+                      if (!strcmp(ttag, "br"))
+                        str = _str_append(str, "\n", &str_len, &str_alloc);
+                      else if (!strcmp(ttag, "\n"))
+                        str = _str_append(str, "\n", &str_len, &str_alloc);
+                      else if (!strcmp(ttag, "\\n"))
+                        str = _str_append(str, "\n", &str_len, &str_alloc);
+                      else if (!strcmp(ttag, "\t"))
+                        str = _str_append(str, "\t", &str_len, &str_alloc);
+                      else if (!strcmp(ttag, "\\t"))
+                        str = _str_append(str, "\t", &str_len, &str_alloc);
+                      else if (!strcmp(ttag, "ps")) /* Unicode paragraph separator */
+                        str = _str_append(str, "\xE2\x80\xA9", &str_len, &str_alloc);
+                      free(ttag);
+                   }
+                 tag_start = tag_end = NULL;
+              }
+            else if (esc_end)
+              {
+                 ts = malloc(esc_end - esc_start + 1);
+                 if (ts)
+                   {
+                      const char *esc;
+                      _str_ncpy(ts, esc_start, esc_end - esc_start);
+                      ts[esc_end - esc_start] = 0;
+                      esc = evas_textblock_escape_string_get(ts);
+                      if (esc)
+                        str = _str_append(str, esc, &str_len, &str_alloc);
+                      free(ts);
+                   }
+                 esc_start = esc_end = NULL;
+              }
+            else if ((!*p) && (s))
+              {
+                 ts = malloc(p - s + 1);
+                 if (ts)
+                   {
+                      _str_ncpy(ts, s, p - s);
+                      ts[p - s] = 0;
+                      str = _str_append(str, ts, &str_len, &str_alloc);
+                      free(ts);
+                   }
+                  break;
+              }
+         }
+       if (*p == '<')
+         {
+            if ((s) && (!esc_start))
+              {
+                 tag_start = p;
+                 tag_end = NULL;
+                 ts = malloc(p - s + 1);
+                 if (ts)
+                   {
+                      _str_ncpy(ts, s, p - s);
+                      ts[p - s] = 0;
+                      str = _str_append(str, ts, &str_len, &str_alloc);
+                      free(ts);
+                   }
+                 s = NULL;
+              }
+         }
+       else if (*p == '>')
+         {
+            if (tag_start)
+              {
+                 tag_end = p;
+                 s = p + 1;
+              }
+         }
+       else if (*p == '&')
+         {
+            if ((s) && (!tag_start))
+              {
+                 esc_start = p;
+                 esc_end = NULL;
+                 ts = malloc(p - s + 1);
+                 if (ts)
+                   {
+                      _str_ncpy(ts, s, p - s);
+                      ts[p - s] = 0;
+                      str = _str_append(str, ts, &str_len, &str_alloc);
+                      free(ts);
+                   }
+                 s = NULL;
+              }
+         }
+       else if (*p == ';')
+         {
+            if (esc_start)
+              {
+                 esc_end = p;
+                 s = p + 1;
+              }
+         }
+       p++;
+     }
+   return str;
+}
+
+char *
+_elm_util_text_to_mkup(const char *text)
+{
+   char *str = NULL;
+   int str_len = 0, str_alloc = 0;
+   int ch, pos = 0, pos2 = 0;
+
+   if (!text) return NULL;
+   for (;;)
+     {
+       pos = pos2;
+        pos2 = evas_string_char_next_get((char *)(text), pos2, &ch);
+        if ((ch <= 0) || (pos2 <= 0)) break;
+       if (ch == '\n')
+          str = _str_append(str, "<br>", &str_len, &str_alloc);
+       else if (ch == '\t')
+          str = _str_append(str, "<\t>", &str_len, &str_alloc);
+       else if (ch == '<')
+          str = _str_append(str, "&lt;", &str_len, &str_alloc);
+       else if (ch == '>')
+          str = _str_append(str, "&gt;", &str_len, &str_alloc);
+       else if (ch == '&')
+          str = _str_append(str, "&amp;", &str_len, &str_alloc);
+        else if (ch == 0x2029) /* PS */
+          str = _str_append(str, "<ps>", &str_len, &str_alloc);
+       else
+         {
+            char tstr[16];
+
+            _str_ncpy(tstr, text + pos, pos2 - pos);
+            tstr[pos2 - pos] = 0;
+            str = _str_append(str, tstr, &str_len, &str_alloc);
+         }
+     }
+   return str;
+}
diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c
new file mode 100644 (file)
index 0000000..e3e1e5a
--- /dev/null
@@ -0,0 +1,2758 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+static const char SMART_NAME[] = "elm_widget";
+
+#define API_ENTRY \
+   Smart_Data *sd = evas_object_smart_data_get(obj); \
+   if ((!obj) || (!sd) || (!_elm_widget_is(obj)))
+#define INTERNAL_ENTRY \
+   Smart_Data *sd = evas_object_smart_data_get(obj); \
+   if (!sd) return;
+
+typedef struct _Smart_Data Smart_Data;
+typedef struct _Edje_Signal_Data Edje_Signal_Data;
+typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
+
+struct _Smart_Data
+{
+   Evas_Object   *obj;
+   const char    *type;
+   Evas_Object   *parent_obj;
+   Evas_Coord     x, y, w, h;
+   Eina_List     *subobjs;
+   Evas_Object   *resize_obj;
+   Evas_Object   *hover_obj;
+   Eina_List     *tooltips, *cursors;
+   void         (*del_func) (Evas_Object *obj);
+   void         (*del_pre_func) (Evas_Object *obj);
+   void         (*focus_func) (Evas_Object *obj);
+   void         (*activate_func) (Evas_Object *obj);
+   void         (*disable_func) (Evas_Object *obj);
+   void         (*theme_func) (Evas_Object *obj);
+   Eina_Bool    (*event_func) (Evas_Object *obj, Evas_Object *source, Evas_Callback_Type type, void *event_info);
+   void         (*signal_func) (Evas_Object *obj, const char *emission,
+                               const char *source);
+   void         (*callback_add_func) (Evas_Object *obj, const char *emission,
+                               const char *source, void (*func) (void *data,
+                                  Evas_Object *o, const char *emission,
+                                  const char *source), void *data);
+   void         (*callback_del_func) (Evas_Object *obj, const char *emission,
+                                 const char *source, void (*func) (void *data,
+                                    Evas_Object *o, const char *emission,
+                                    const char *source), void *data);
+   void         (*changed_func) (Evas_Object *obj);
+   Eina_Bool    (*focus_next_func) (const Evas_Object *obj, Elm_Focus_Direction dir,
+                                    Evas_Object **next);
+   void         (*on_focus_func) (void *data, Evas_Object *obj);
+   void          *on_focus_data;
+   void         (*on_change_func) (void *data, Evas_Object *obj);
+   void          *on_change_data;
+   void         (*on_show_region_func) (void *data, Evas_Object *obj);
+   void          *on_show_region_data;
+   void         (*focus_region_func) (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+   void         (*on_focus_region_func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+   void          *data;
+   Evas_Coord     rx, ry, rw, rh;
+   int            scroll_hold;
+   int            scroll_freeze;
+   double         scale;
+   Elm_Theme     *theme;
+   const char    *style;
+   unsigned int   focus_order;
+   Eina_Bool      focus_order_on_calc;
+   
+   int            child_drag_x_locked;
+   int            child_drag_y_locked;
+
+   Eina_List     *edje_signals;
+
+   Eina_Bool      drag_x_locked : 1;
+   Eina_Bool      drag_y_locked : 1;
+   
+   Eina_Bool      can_focus : 1;
+   Eina_Bool      child_can_focus : 1;
+   Eina_Bool      focused : 1;
+   Eina_Bool      highlight_ignore : 1;
+   Eina_Bool      highlight_in_theme : 1;
+   Eina_Bool      disabled : 1;
+
+   Eina_List     *focus_chain;
+   Eina_List     *event_cb;
+};
+
+struct _Edje_Signal_Data
+{
+   Evas_Object *obj;
+   Edje_Signal_Cb func;
+   const char *emission;
+   const char *source;
+   void *data;
+};
+
+struct _Elm_Event_Cb_Data {
+     Elm_Event_Cb func;
+     const void *data;
+};
+
+/* local subsystem functions */
+static void _smart_reconfigure(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_calculate(Evas_Object *obj);
+static void _smart_init(void);
+
+static void _if_focused_revert(Evas_Object *obj, Eina_Bool can_focus_only);
+static Evas_Object *_newest_focus_order_get(Evas_Object *obj, unsigned int *newest_focus_order, Eina_Bool can_focus_only);
+
+/* local subsystem globals */
+static Evas_Smart *_e_smart = NULL;
+static Eina_List  *widtypes = NULL;
+
+static unsigned int focus_order = 0;
+
+// internal funcs
+static inline Eina_Bool
+_elm_widget_is(const Evas_Object *obj)
+{
+   const char *type = evas_object_type_get(obj);
+   return type == SMART_NAME;
+}
+
+static inline Eina_Bool
+_is_focusable(Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->can_focus || (sd->child_can_focus);
+}
+
+static void
+_unfocus_parents(Evas_Object *obj)
+{
+   for (; obj; obj = elm_widget_parent_get(obj))
+     {
+        Smart_Data *sd = evas_object_smart_data_get(obj);
+        if (!sd) return;
+        if (!sd->focused) return;
+        sd->focused = 0;
+     }
+}
+
+static void
+_focus_parents(Evas_Object *obj)
+{
+   for (; obj; obj = elm_widget_parent_get(obj))
+     {
+        Smart_Data *sd = evas_object_smart_data_get(obj);
+        if (!sd) return;
+        if (sd->focused) return;
+        sd->focused = 1;
+     }
+}
+
+static void
+_sub_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Smart_Data *sd = data;
+
+   if (_elm_widget_is(obj))
+     {
+        if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
+     }
+   if (obj == sd->resize_obj)
+     sd->resize_obj = NULL;
+   else if (obj == sd->hover_obj)
+     sd->hover_obj = NULL;
+   else
+     sd->subobjs = eina_list_remove(sd->subobjs, obj);
+   evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
+}
+
+static void
+_sub_obj_mouse_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Evas_Object *o = obj;
+   do 
+     {
+        if (_elm_widget_is(o)) break;
+        o = evas_object_smart_parent_get(o);
+     }
+   while (o);
+   if (!o) return;
+   if (!_is_focusable(o)) return;
+   elm_widget_focus_steal(o);
+}
+
+static void
+_propagate_x_drag_lock(Evas_Object *obj, int dir)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (sd->parent_obj)
+     {
+        Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
+        if (sd2)
+          {
+             sd2->child_drag_x_locked += dir;
+             _propagate_x_drag_lock(sd->parent_obj, dir);
+          }
+     }
+}
+
+static void
+_propagate_y_drag_lock(Evas_Object *obj, int dir)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (sd->parent_obj)
+     {
+        Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
+        if (sd2)
+          {
+             sd2->child_drag_y_locked += dir;
+             _propagate_y_drag_lock(sd->parent_obj, dir);
+          }
+     }
+}
+
+static void
+_propagate_event(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   INTERNAL_ENTRY;
+   Evas_Callback_Type type = (Evas_Callback_Type)(long) data;
+   Evas_Event_Flags *event_flags = NULL;
+
+   switch (type)
+     {
+     case EVAS_CALLBACK_KEY_DOWN:
+          {
+             Evas_Event_Key_Down *ev = event_info;
+             event_flags = &(ev->event_flags);
+             break;
+          }
+     case EVAS_CALLBACK_KEY_UP:
+          {
+             Evas_Event_Key_Up *ev = event_info;
+             event_flags = &(ev->event_flags);
+             break;
+          }
+     case EVAS_CALLBACK_MOUSE_WHEEL:
+          {
+             Evas_Event_Mouse_Wheel *ev = event_info;
+             event_flags = &(ev->event_flags);
+             break;
+          }
+     default:
+        break;
+     }
+
+   elm_widget_event_propagate(obj, type, event_info, event_flags);
+}
+
+static void
+_parent_focus(Evas_Object *obj)
+{
+   API_ENTRY return;
+
+   Evas_Object *o = elm_widget_parent_get(obj);
+   sd->focus_order_on_calc = EINA_TRUE;
+
+   if (sd->focused) return;
+   if (o)
+     {
+       unsigned int i = 0;
+       Evas_Object *ret;
+
+       ret = _newest_focus_order_get(o, &i, EINA_TRUE);
+
+       /* we don't want to bump a common widget ancestor's
+          focus_order *twice* while parent focusing */
+       if (!ret || (!i) || (i != focus_order))
+         _parent_focus(o);
+     }
+
+   if (!sd->focus_order_on_calc)
+     return; /* we don't want to override it if by means of any of the
+               callbacks below one gets to calculate our order
+               first. */
+
+   focus_order++;
+   sd->focus_order = focus_order;
+   sd->focused = EINA_TRUE;
+   if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
+   if (sd->focus_func) sd->focus_func(obj);
+
+   _elm_widget_focus_region_show(obj);
+
+   sd->focus_order_on_calc = EINA_FALSE;
+}
+
+static void
+_elm_object_focus_chain_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Smart_Data *sd = data;
+
+   sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
+}
+
+// exposed util funcs to elm
+void
+_elm_widget_type_clear(void)
+{
+   const char **ptr;
+   
+   EINA_LIST_FREE(widtypes, ptr)
+     {
+        eina_stringshare_del(*ptr);
+        *ptr = NULL;
+     }
+}
+
+void
+_elm_widget_focus_region_show(const Evas_Object *obj)
+{
+   Evas_Coord x, y, w, h, ox, oy;
+   Smart_Data *sd2;
+   Evas_Object *o;
+
+   API_ENTRY return;
+
+   o = elm_widget_parent_get(obj);
+   if (!o) return;
+
+   elm_widget_focus_region_get(obj, &x, &y, &w, &h);
+   evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
+   while (o)
+     {
+        Evas_Coord px, py;
+        sd2 = evas_object_smart_data_get(o);
+        if (sd2->focus_region_func)
+          {
+             sd2->focus_region_func(o, x, y, w, h);
+             elm_widget_focus_region_get(o, &x, &y, &w, &h);
+          }
+        else
+          {
+             evas_object_geometry_get(o, &px, &py, NULL, NULL);
+             x += ox - px;
+             y += oy - py;
+             ox = px;
+             oy = py;
+          }
+        o = elm_widget_parent_get(o);
+     }
+}
+
+/**
+ * @defgroup Widget Widget
+ *
+ * @internal
+ * Exposed api for making widgets
+ */
+EAPI void
+elm_widget_type_register(const char **ptr)
+{
+   widtypes = eina_list_append(widtypes, (void *)ptr);
+}
+
+EAPI Eina_Bool
+elm_widget_api_check(int ver)
+{
+   if (ver != ELM_INTERNAL_API_VERSION)
+     {
+        CRITICAL("Elementary widget api versions do not match");
+        return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+
+EAPI Evas_Object *
+elm_widget_add(Evas *evas)
+{
+   _smart_init();
+   return evas_object_smart_add(evas, _e_smart);
+}
+
+EAPI void
+elm_widget_del_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->del_func = func;
+}
+
+EAPI void
+elm_widget_del_pre_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->del_pre_func = func;
+}
+
+EAPI void
+elm_widget_focus_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->focus_func = func;
+}
+
+EAPI void
+elm_widget_activate_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->activate_func = func;
+}
+
+EAPI void
+elm_widget_disable_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->disable_func = func;
+}
+
+EAPI void
+elm_widget_theme_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->theme_func = func;
+}
+
+EAPI void
+elm_widget_event_hook_set(Evas_Object *obj, Eina_Bool (*func) (Evas_Object *obj, Evas_Object *source, Evas_Callback_Type type, void *event_info))
+{
+   API_ENTRY return;
+   sd->event_func = func;
+}
+
+EAPI void
+elm_widget_changed_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->changed_func = func;
+}
+
+EAPI void
+elm_widget_signal_emit_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source))
+{
+   API_ENTRY return;
+   sd->signal_func = func;
+}
+
+EAPI void
+elm_widget_signal_callback_add_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data))
+{
+   API_ENTRY return;
+   sd->callback_add_func = func;
+}
+
+EAPI void
+elm_widget_signal_callback_del_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data))
+{
+   API_ENTRY return;
+   sd->callback_del_func = func;
+}
+
+EAPI void
+elm_widget_theme(Evas_Object *obj)
+{
+   const Eina_List *l;
+   Evas_Object *child;
+   Elm_Tooltip *tt;
+   Elm_Cursor *cur;
+
+   API_ENTRY return;
+   EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_theme(child);
+   if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
+   if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
+   EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
+   EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
+   if (sd->theme_func) sd->theme_func(obj);
+}
+
+EAPI void
+elm_widget_theme_specific(Evas_Object *obj, Elm_Theme *th, Eina_Bool force)
+{
+   const Eina_List *l;
+   Evas_Object *child;
+   Elm_Tooltip *tt;
+   Elm_Cursor *cur;
+   Elm_Theme *th2, *thdef;
+
+   API_ENTRY return;
+   thdef = elm_theme_default_get();
+   if (!th) th = thdef;
+   if (!force)
+     {
+        th2 = sd->theme;
+        if (!th2) th2 = thdef;
+        while (th2)
+          {
+             if (th2 == th)
+               {
+                  force = EINA_TRUE;
+                  break;
+               }
+             if (th2 == thdef) break;
+             th2 = th2->ref_theme;
+             if (!th2) th2 = thdef;
+          }
+     }
+   if (!force) return;
+   EINA_LIST_FOREACH(sd->subobjs, l, child)
+     elm_widget_theme_specific(child, th, force);
+   if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
+   if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
+   EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
+   EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
+   if (sd->theme_func) sd->theme_func(obj);
+}
+
+/**
+ * @internal
+ *
+ * Set hook to get next object in object focus chain.
+ *
+ * @param obj The widget object.
+ * @param func The hook to be used with this widget.
+ *
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_next_hook_set(Evas_Object *obj, Eina_Bool (*func) (const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next))
+{
+   API_ENTRY return;
+   sd->focus_next_func = func;
+}
+
+EAPI void
+elm_widget_on_focus_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data)
+{
+   API_ENTRY return;
+   sd->on_focus_func = func;
+   sd->on_focus_data = data;
+}
+
+EAPI void
+elm_widget_on_change_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data)
+{
+   API_ENTRY return;
+   sd->on_change_func = func;
+   sd->on_change_data = data;
+}
+
+EAPI void
+elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data)
+{
+   API_ENTRY return;
+   sd->on_show_region_func = func;
+   sd->on_show_region_data = data;
+}
+
+/**
+ * @internal
+ *
+ * Set the hook to use to show the focused region.
+ *
+ * Whenever a new widget gets focused or it's needed to show the focused
+ * area of the current one, this hook will be called on objects that may
+ * want to move their children into their visible area.
+ * The area given in the hook function is relative to the @p obj widget.
+ *
+ * @param obj The widget object
+ * @param func The function to call to show the specified area.
+ *
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_region_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h))
+{
+   API_ENTRY return;
+   sd->focus_region_func = func;
+}
+
+/**
+ * @internal
+ *
+ * Set the hook to retrieve the focused region of a widget.
+ *
+ * This hook will be called by elm_widget_focus_region_get() whenever
+ * it's needed to get the focused area of a widget. The area must be relative
+ * to the widget itself and if no hook is set, it will default to the entire
+ * object.
+ *
+ * @param obj The widget object
+ * @param func The function used to retrieve the focus region.
+ *
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_on_focus_region_hook_set(Evas_Object *obj, void (*func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h))
+{
+   API_ENTRY return;
+   sd->on_focus_region_func = func;
+}
+
+EAPI void
+elm_widget_data_set(Evas_Object *obj, void *data)
+{
+   API_ENTRY return;
+   sd->data = data;
+}
+
+EAPI void *
+elm_widget_data_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   return sd->data;
+}
+
+EAPI void
+elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj)
+{
+   API_ENTRY return;
+   double scale, pscale = elm_widget_scale_get(sobj);
+   Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
+
+   if (_elm_widget_is(sobj))
+     {
+        Smart_Data *sd2 = evas_object_smart_data_get(sobj);
+        if (sd2)
+          {
+             if (sd2->parent_obj == obj)
+               return;
+             elm_widget_sub_object_del(sd2->parent_obj, sobj);
+             sd2->parent_obj = obj;
+             if (!sd->child_can_focus && (_is_focusable(sobj)))
+               sd->child_can_focus = EINA_TRUE;
+          }
+     }
+   else
+     {
+        void *data = evas_object_data_get(sobj, "elm-parent");
+        if (data)
+          {
+             if (data == obj) return;
+             evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL, 
+                                            _sub_obj_del);
+          }
+     }
+
+   sd->subobjs = eina_list_append(sd->subobjs, sobj);
+   evas_object_data_set(sobj, "elm-parent", obj);
+   evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
+   evas_object_smart_callback_call(obj, "sub-object-add", sobj);
+   scale = elm_widget_scale_get(sobj);
+   th = elm_widget_theme_get(sobj);
+   if ((scale != pscale) || (th != pth)) elm_widget_theme(sobj);
+   if (elm_widget_focus_get(sobj)) _focus_parents(obj);
+}
+
+EAPI void
+elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj)
+{
+   Evas_Object *sobj_parent;
+   API_ENTRY return;
+   if (!sobj) return;
+
+   sobj_parent = evas_object_data_del(sobj, "elm-parent");
+   if (sobj_parent != obj)
+     {
+       static int abort_on_warn = -1;
+       ERR("removing sub object %p from parent %p, "
+           "but elm-parent is different %p!",
+           sobj, obj, sobj_parent);
+       if (EINA_UNLIKELY(abort_on_warn == -1))
+         {
+            if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
+            else abort_on_warn = 0;
+         }
+       if (abort_on_warn == 1) abort();
+     }
+   if (!sd->child_can_focus)
+     {
+       if (_is_focusable(sobj)) sd->child_can_focus = 0;
+     }
+   if (_elm_widget_is(sobj))
+     {
+        Smart_Data *sd2 = evas_object_smart_data_get(sobj);
+        if (sd2)
+          {
+             sd2->parent_obj = NULL;
+             if (sd2->resize_obj == sobj)
+               sd2->resize_obj = NULL;
+             else
+               sd->subobjs = eina_list_remove(sd->subobjs, sobj);
+          }
+        else
+          sd->subobjs = eina_list_remove(sd->subobjs, sobj);
+        if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
+     }
+   else
+     sd->subobjs = eina_list_remove(sd->subobjs, sobj);
+   evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, 
+                                       _sub_obj_del, sd);
+   evas_object_smart_callback_call(obj, "sub-object-del", sobj);
+}
+
+EAPI void
+elm_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj)
+{
+   API_ENTRY return;
+   // orphan previous resize obj
+   if (sd->resize_obj)
+     {
+       evas_object_clip_unset(sd->resize_obj);
+       evas_object_data_del(sd->resize_obj, "elm-parent");
+       if (_elm_widget_is(sd->resize_obj))
+         {
+            Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
+            if (sd2) sd2->parent_obj = NULL;
+         }
+       evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
+                                            _sub_obj_del, sd);
+       evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                            _sub_obj_mouse_down, sd);
+       evas_object_smart_member_del(sd->resize_obj);
+        if (_elm_widget_is(sd->resize_obj))
+          {
+             if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
+          }
+     }
+   // orphan new resize obj
+   if (sobj)
+     {
+        evas_object_data_del(sobj, "elm-parent");
+        if (_elm_widget_is(sobj))
+          {
+             Smart_Data *sd2 = evas_object_smart_data_get(sobj);
+             if (sd2) sd2->parent_obj = NULL;
+          }
+        evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
+                                            _sub_obj_del, sd);
+        evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
+                                            _sub_obj_mouse_down, sd);
+        evas_object_smart_member_del(sobj);
+        if (_elm_widget_is(sobj))
+          {
+             if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
+          }
+     }
+   // set the resize obj up
+   sd->resize_obj = sobj;
+   if (sd->resize_obj)
+     {
+       if (_elm_widget_is(sd->resize_obj))
+         {
+            Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
+            if (sd2) sd2->parent_obj = obj;
+         }
+       evas_object_clip_set(sobj, evas_object_clip_get(obj));
+       evas_object_smart_member_add(sobj, obj);
+       evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
+                                       _sub_obj_del, sd);
+       evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
+                                       _sub_obj_mouse_down, sd);
+       _smart_reconfigure(sd);
+       evas_object_data_set(sobj, "elm-parent", obj);
+       evas_object_smart_callback_call(obj, "sub-object-add", sobj);
+        if (_elm_widget_is(sobj))
+          {
+             if (elm_widget_focus_get(sobj)) _focus_parents(obj);
+          }
+     }
+}
+
+EAPI void
+elm_widget_hover_object_set(Evas_Object *obj, Evas_Object *sobj)
+{
+   API_ENTRY return;
+   if (sd->hover_obj)
+     {
+       evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
+           _sub_obj_del, sd);
+     }
+   sd->hover_obj = sobj;
+   if (sd->hover_obj)
+     {
+       evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
+                                       _sub_obj_del, sd);
+       _smart_reconfigure(sd);
+     }
+}
+
+EAPI void
+elm_widget_can_focus_set(Evas_Object *obj, Eina_Bool can_focus)
+{
+   API_ENTRY return;
+   sd->can_focus = can_focus;
+   if (can_focus)
+     {
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
+                                       _propagate_event,
+                                       (void *)(long) EVAS_CALLBACK_KEY_DOWN);
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
+                                       _propagate_event,
+                                       (void *)(long) EVAS_CALLBACK_KEY_UP);
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
+                                       _propagate_event,
+                                       (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
+     }
+   else
+     {
+        evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
+                                       _propagate_event);
+        evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
+                                       _propagate_event);
+        evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
+                                       _propagate_event);
+     }
+}
+
+EAPI Eina_Bool
+elm_widget_can_focus_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->can_focus;
+}
+
+EAPI Eina_Bool
+elm_widget_child_can_focus_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->child_can_focus;
+}
+
+EAPI void
+elm_widget_highlight_ignore_set(Evas_Object *obj, Eina_Bool ignore)
+{
+   API_ENTRY return;
+   sd->highlight_ignore = !!ignore;
+}
+
+EAPI Eina_Bool
+elm_widget_highlight_ignore_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->highlight_ignore;
+}
+
+EAPI void
+elm_widget_highlight_in_theme_set(Evas_Object *obj, Eina_Bool highlight)
+{
+   API_ENTRY return;
+   sd->highlight_in_theme = !!highlight;
+   /* FIXME: if focused, it should switch from one mode to the other */
+}
+
+EAPI Eina_Bool
+elm_widget_highlight_in_theme_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->highlight_in_theme;
+}
+
+EAPI Eina_Bool
+elm_widget_focus_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->focused;
+}
+
+EAPI Evas_Object *
+elm_widget_focused_object_get(const Evas_Object *obj)
+{
+   const Evas_Object *subobj;
+   const Eina_List *l;
+   API_ENTRY return NULL;
+
+   if (!sd->focused) return NULL;
+   EINA_LIST_FOREACH(sd->subobjs, l, subobj)
+     {
+       Evas_Object *fobj = elm_widget_focused_object_get(subobj);
+       if (fobj) return fobj;
+     }
+   return (Evas_Object *)obj;
+}
+
+EAPI Evas_Object *
+elm_widget_top_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
+   return (Evas_Object *)obj;
+}
+
+EAPI Eina_Bool
+elm_widget_is(const Evas_Object *obj)
+{
+   return _elm_widget_is(obj);
+}
+
+EAPI Evas_Object *
+elm_widget_parent_widget_get(const Evas_Object *obj)
+{
+   Evas_Object *parent;
+
+   if (_elm_widget_is(obj))
+     {
+       Smart_Data *sd = evas_object_smart_data_get(obj);
+       if (!sd) return NULL;
+       parent = sd->parent_obj;
+     }
+   else
+     {
+       parent = evas_object_data_get(obj, "elm-parent");
+       if (!parent) parent = evas_object_smart_parent_get(obj);
+     }
+
+   while (parent)
+     {
+       Evas_Object *elm_parent;
+       if (_elm_widget_is(parent)) break;
+       elm_parent = evas_object_data_get(parent, "elm-parent");
+        if (elm_parent) parent = elm_parent;
+       else parent = evas_object_smart_parent_get(parent);
+     }
+   return parent;
+}
+
+EAPI void
+elm_widget_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data)
+{
+   API_ENTRY return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+   Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
+   ecb->func = func;
+   ecb->data = data;
+   sd->event_cb = eina_list_append(sd->event_cb, ecb);
+}
+
+EAPI void *
+elm_widget_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data)
+{
+   API_ENTRY return NULL;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
+   Eina_List *l;
+   Elm_Event_Cb_Data *ecd;
+   EINA_LIST_FOREACH(sd->event_cb, l, ecd)
+      if ((ecd->func == func) && (ecd->data == data))
+        {
+           free(ecd);
+           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
+           return (void *)data;
+        }
+   return NULL;
+}
+
+EAPI Eina_Bool
+elm_widget_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags)
+{
+   API_ENTRY return EINA_FALSE; //TODO reduce.
+   if (!_elm_widget_is(obj)) return EINA_FALSE;
+   Evas_Object *parent = obj;
+   Elm_Event_Cb_Data *ecd;
+   Eina_List *l, *l_prev;
+
+   while (parent &&
+          (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
+     {
+        sd = evas_object_smart_data_get(parent);
+        if ((!sd) || (!_elm_widget_is(obj)))
+          return EINA_FALSE; //Not Elm Widget
+
+        if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
+          return EINA_TRUE;
+
+        EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
+          {
+             if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
+                 (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
+                 return EINA_TRUE;
+          }
+        parent = sd->parent_obj;
+     }
+
+   return EINA_FALSE;
+}
+
+/**
+ * @internal
+ *
+ * Set custom focus chain.
+ *
+ * This function i set one new and overwrite any previous custom focus chain
+ * with the list of objects. The previous list will be deleted and this list
+ * will be managed. After setted, don't modity it.
+ *
+ * @note On focus cycle, only will be evaluated children of this container.
+ *
+ * @param obj The container widget
+ * @param objs Chain of objects to pass focus
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs)
+{
+   API_ENTRY return;
+   if (!sd->focus_next_func)
+     return;
+
+   elm_widget_focus_custom_chain_unset(obj);
+
+   Eina_List *l;
+   Evas_Object *o;
+
+   EINA_LIST_FOREACH(objs, l, o)
+     {
+        evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
+                                       _elm_object_focus_chain_del_cb, sd);
+     }
+
+   sd->focus_chain = objs;
+}
+
+/**
+ * @internal
+ *
+ * Get custom focus chain
+ *
+ * @param obj The container widget
+ * @ingroup Widget
+ */
+EAPI const Eina_List *
+elm_widget_focus_custom_chain_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   return (const Eina_List *) sd->focus_chain;
+}
+
+/**
+ * @internal
+ *
+ * Unset custom focus chain
+ *
+ * @param obj The container widget
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_custom_chain_unset(Evas_Object *obj)
+{
+   API_ENTRY return;
+   Eina_List *l, *l_next;
+   Evas_Object *o;
+
+   EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
+     {
+        evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
+                                            _elm_object_focus_chain_del_cb, sd);
+        sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
+     }
+}
+
+/**
+ * @internal
+ *
+ * Append object to custom focus chain.
+ *
+ * @note If relative_child equal to NULL or not in custom chain, the object
+ * will be added in end.
+ *
+ * @note On focus cycle, only will be evaluated children of this container.
+ *
+ * @param obj The container widget
+ * @param child The child to be added in custom chain
+ * @param relative_child The relative object to position the child
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child)
+{
+   API_ENTRY return;
+   EINA_SAFETY_ON_NULL_RETURN(child);
+   if (!sd->focus_next_func)
+     return;
+
+   evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
+                                       _elm_object_focus_chain_del_cb, sd);
+
+   if (!relative_child)
+     {
+        sd->focus_chain = eina_list_append(sd->focus_chain, child);
+        return;
+     }
+
+   sd->focus_chain = eina_list_append_relative(sd->focus_chain, child, relative_child);
+   return;
+}
+
+/**
+ * @internal
+ *
+ * Prepend object to custom focus chain.
+ *
+ * @note If relative_child equal to NULL or not in custom chain, the object
+ * will be added in begin.
+ *
+ * @note On focus cycle, only will be evaluated children of this container.
+ *
+ * @param obj The container widget
+ * @param child The child to be added in custom chain
+ * @param relative_child The relative object to position the child
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child)
+{
+   API_ENTRY return;
+   EINA_SAFETY_ON_NULL_RETURN(child);
+   if (!sd->focus_next_func)
+     return;
+
+   evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
+                                       _elm_object_focus_chain_del_cb, sd);
+
+   if (!relative_child)
+     {
+        sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
+        return;
+     }
+
+   sd->focus_chain = eina_list_prepend_relative(sd->focus_chain, child, relative_child);
+   return;
+}
+
+/**
+ * @internal
+ *
+ * Give focus to next object in object tree.
+ *
+ * Give focus to next object in focus chain of one object sub-tree.
+ * If the last object of chain already have focus, the focus will go to the
+ * first object of chain.
+ *
+ * @param obj The widget root of sub-tree
+ * @param dir Direction to cycle the focus
+ *
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
+{
+   Evas_Object *target = NULL;
+   if (!_elm_widget_is(obj))
+     return;
+   elm_widget_focus_next_get(obj, dir, &target);
+   if (target)
+     elm_widget_focus_steal(target);
+}
+
+/**
+ * @internal
+ *
+ * Give focus to near object in one direction.
+ *
+ * Give focus to near object in direction of one object.
+ * If none focusable object in given direction, the focus will not change.
+ *
+ * @param obj The reference widget
+ * @param x Horizontal component of direction to focus
+ * @param y Vertical component of direction to focus
+ *
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__)
+{
+   return; /* TODO */
+}
+
+/**
+ * @internal
+ *
+ * Get next object in focus chain of object tree.
+ *
+ * Get next object in focus chain of one object sub-tree.
+ * Return the next object by reference. If don't have any candidate to receive
+ * focus before chain end, the first candidate will be returned.
+ *
+ * @param obj The widget root of sub-tree
+ * @param dir Direction os focus chain
+ * @param next The next object in focus chain
+ * @return EINA_TRUE if don't need focus chain restart/loop back
+ *         to use 'next' obj.
+ *
+ * @ingroup Widget
+ */
+EAPI Eina_Bool
+elm_widget_focus_next_get(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   if (!next)
+     return EINA_FALSE;
+   *next = NULL;
+
+   API_ENTRY return EINA_FALSE;
+
+   /* Ignore if disabled */
+   if ((!evas_object_visible_get(obj)) || (elm_widget_disabled_get(obj)))
+     return EINA_FALSE;
+
+   /* Try use hook */
+   if (sd->focus_next_func)
+     return sd->focus_next_func(obj, dir, next);
+
+   if (!elm_widget_can_focus_get(obj))
+     return EINA_FALSE;
+
+   /* Return */
+   *next = (Evas_Object *)obj;
+   return !elm_widget_focus_get(obj);
+}
+
+
+/**
+ * @internal
+ *
+ * Get next object in focus chain of object tree in list.
+ *
+ * Get next object in focus chain of one object sub-tree ordered by one list.
+ * Return the next object by reference. If don't have any candidate to receive
+ * focus before list end, the first candidate will be returned.
+ *
+ * @param obj The widget root of sub-tree
+ * @param dir Direction os focus chain
+ * @param items list with ordered objects
+ * @param list_data_get function to get the object from one item of list
+ * @param next The next object in focus chain
+ * @return EINA_TRUE if don't need focus chain restart/loop back
+ *         to use 'next' obj.
+ *
+ * @ingroup Widget
+ */
+EAPI Eina_Bool
+elm_widget_focus_list_next_get(const Evas_Object *obj, const Eina_List *items, void *(*list_data_get) (const Eina_List *list), Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Eina_List *(*list_next) (const Eina_List *list);
+
+   if (!next)
+     return EINA_FALSE;
+   *next = NULL;
+
+   if (!_elm_widget_is(obj))
+     return EINA_FALSE;
+
+   if (!items)
+     return EINA_FALSE;
+
+   /* Direction */
+   if (dir == ELM_FOCUS_PREVIOUS)
+     {
+        items = eina_list_last(items);
+        list_next = eina_list_prev;
+     }
+   else if (dir == ELM_FOCUS_NEXT)
+     list_next = eina_list_next;
+   else
+     return EINA_FALSE;
+
+   const Eina_List *l = items;
+
+   /* Recovery last focused sub item */
+   if (elm_widget_focus_get(obj))
+     for (; l; l = list_next(l))
+       {
+          Evas_Object *cur = list_data_get(l);
+          if (elm_widget_focus_get(cur)) break;
+       }
+
+   const Eina_List *start = l;
+   Evas_Object *to_focus = NULL;
+
+   /* Interate sub items */
+   /* Go to end of list */
+   for (; l; l = list_next(l))
+     {
+        Evas_Object *tmp = NULL;
+        Evas_Object *cur = list_data_get(l);
+
+        if (elm_widget_parent_get(cur) != obj)
+          continue;
+
+        /* Try Focus cycle in subitem */
+        if (elm_widget_focus_next_get(cur, dir, &tmp))
+          {
+             *next = tmp;
+             return EINA_TRUE;
+          }
+        else if ((tmp) && (!to_focus))
+          to_focus = tmp;
+     }
+
+   l = items;
+
+   /* Get First possible */
+   for (;l != start; l = list_next(l))
+     {
+        Evas_Object *tmp = NULL;
+        Evas_Object *cur = list_data_get(l);
+
+        if (elm_widget_parent_get(cur) != obj)
+          continue;
+
+        /* Try Focus cycle in subitem */
+        elm_widget_focus_next_get(cur, dir, &tmp);
+        if (tmp)
+          {
+             *next = tmp;
+             return EINA_FALSE;
+          }
+     }
+
+   *next = to_focus;
+   return EINA_FALSE;
+}
+
+EAPI void
+elm_widget_signal_emit(Evas_Object *obj, const char *emission, const char *source)
+{
+   API_ENTRY return;
+   if (!sd->signal_func) return;
+   sd->signal_func(obj, emission, source);
+}
+
+static void
+_edje_signal_callback(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source)
+{
+   Edje_Signal_Data *esd = data;
+   esd->func(esd->data, esd->obj, emission, source);
+}
+
+EAPI void
+elm_widget_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
+{
+   Edje_Signal_Data *esd;
+   API_ENTRY return;
+   if (!sd->callback_add_func) return;
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   esd = ELM_NEW(Edje_Signal_Data);
+   if (!esd) return;
+
+   esd->obj = obj;
+   esd->func = func;
+   esd->emission = eina_stringshare_add(emission);
+   esd->source = eina_stringshare_add(source);
+   esd->data = data;
+   sd->edje_signals = eina_list_append(sd->edje_signals, esd);
+   sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
+}
+
+EAPI void *
+elm_widget_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source))
+{
+   Edje_Signal_Data *esd;
+   Eina_List *l;
+   void *data = NULL;
+   API_ENTRY return NULL;
+   if (!sd->callback_del_func) return NULL;
+
+   EINA_LIST_FOREACH(sd->edje_signals, l, esd)
+     {
+        if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
+            (!strcmp(esd->source, source)))
+          {
+             sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
+             eina_stringshare_del(esd->emission);
+             eina_stringshare_del(esd->source);
+             data = esd->data;
+             free(esd);
+             break;
+          }
+     }
+   sd->callback_del_func(obj, emission, source, _edje_signal_callback, esd);
+   return data;
+}
+
+EAPI void
+elm_widget_focus_set(Evas_Object *obj, int first)
+{
+   API_ENTRY return;
+   if (!sd->focused)
+     {
+        focus_order++;
+        sd->focus_order = focus_order;
+       sd->focused = EINA_TRUE;
+       if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
+     }
+   if (sd->focus_func)
+     {
+       sd->focus_func(obj);
+       return;
+     }
+   else
+     {
+       if (first)
+         {
+            if ((_is_focusable(sd->resize_obj)) &&
+                (!elm_widget_disabled_get(sd->resize_obj)))
+              {
+                 elm_widget_focus_set(sd->resize_obj, first);
+              }
+            else
+              {
+                 const Eina_List *l;
+                 Evas_Object *child;
+                 EINA_LIST_FOREACH(sd->subobjs, l, child)
+                   {
+                      if ((_is_focusable(child)) &&
+                          (!elm_widget_disabled_get(child)))
+                        {
+                           elm_widget_focus_set(child, first);
+                           break;
+                        }
+                   }
+              }
+         }
+       else
+         {
+            const Eina_List *l;
+            Evas_Object *child;
+            EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
+              {
+                 if ((_is_focusable(child)) &&
+                     (!elm_widget_disabled_get(child)))
+                   {
+                      elm_widget_focus_set(child, first);
+                      break;
+                   }
+              }
+            if (!l)
+              {
+                 if ((_is_focusable(sd->resize_obj)) &&
+                     (!elm_widget_disabled_get(sd->resize_obj)))
+                   {
+                      elm_widget_focus_set(sd->resize_obj, first);
+                   }
+              }
+         }
+     }
+}
+
+EAPI Evas_Object *
+elm_widget_parent_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   return sd->parent_obj;
+}
+
+EAPI void
+elm_widget_focused_object_clear(Evas_Object *obj)
+{
+   API_ENTRY return;
+   if (!sd->focused) return;
+   if (elm_widget_focus_get(sd->resize_obj))
+      elm_widget_focused_object_clear(sd->resize_obj);
+   else
+     {
+       const Eina_List *l;
+       Evas_Object *child;
+       EINA_LIST_FOREACH(sd->subobjs, l, child)
+         {
+            if (elm_widget_focus_get(child))
+              {
+                 elm_widget_focused_object_clear(child);
+                 break;
+              }
+         }
+     }
+   sd->focused = EINA_FALSE;
+   if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
+   if (sd->focus_func) sd->focus_func(obj);
+}
+
+EAPI void
+elm_widget_focus_steal(Evas_Object *obj)
+{
+   Evas_Object *parent, *o;
+   API_ENTRY return;
+
+   if (sd->focused) return;
+   if (sd->disabled) return;
+   parent = obj;
+   for (;;)
+     {
+       o = elm_widget_parent_get(parent);
+       if (!o) break;
+       sd = evas_object_smart_data_get(o);
+       if (sd->focused) break;
+       parent = o;
+     }
+   if (!elm_widget_parent_get(parent))
+     elm_widget_focused_object_clear(parent);
+   else
+     {
+       parent = elm_widget_parent_get(parent);
+       sd = evas_object_smart_data_get(parent);
+       if (elm_widget_focus_get(sd->resize_obj))
+          {
+             elm_widget_focused_object_clear(sd->resize_obj);
+          }
+       else
+         {
+            const Eina_List *l;
+            Evas_Object *child;
+            EINA_LIST_FOREACH(sd->subobjs, l, child)
+              {
+                 if (elm_widget_focus_get(child))
+                   {
+                      elm_widget_focused_object_clear(child);
+                      break;
+                   }
+              }
+         }
+     }
+   _parent_focus(obj);
+   return;
+}
+
+EAPI void
+elm_widget_activate(Evas_Object *obj)
+{
+   API_ENTRY return;
+   elm_widget_change(obj);
+   if (sd->activate_func) sd->activate_func(obj);
+}
+
+EAPI void
+elm_widget_change(Evas_Object *obj)
+{
+   API_ENTRY return;
+   elm_widget_change(elm_widget_parent_get(obj));
+   if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
+}
+
+EAPI void
+elm_widget_disabled_set(Evas_Object *obj, int disabled)
+{
+   API_ENTRY return;
+
+   if (sd->disabled == disabled) return;
+   sd->disabled = disabled;
+   if (sd->focused)
+     {
+       Evas_Object *o, *parent;
+
+       parent = obj;
+       for (;;)
+         {
+            o = elm_widget_parent_get(parent);
+            if (!o) break;
+            parent = o;
+         }
+        if (elm_widget_focus_get(obj))
+          elm_widget_focus_cycle(parent, ELM_FOCUS_NEXT);
+     }
+   if (sd->disable_func) sd->disable_func(obj);
+}
+
+EAPI int
+elm_widget_disabled_get(const Evas_Object *obj)
+{
+   API_ENTRY return 0;
+   return sd->disabled;
+}
+
+EAPI void
+elm_widget_show_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   Evas_Object *parent_obj, *child_obj;
+   Evas_Coord px, py, cx, cy;
+
+   API_ENTRY return;
+   if ((x == sd->rx) && (y == sd->ry) && (w == sd->rw) && (h == sd->rh)) return;
+   sd->rx = x;
+   sd->ry = y;
+   sd->rw = w;
+   sd->rh = h;
+   if (sd->on_show_region_func)
+      sd->on_show_region_func(sd->on_show_region_data, obj);
+
+   do
+     {
+        parent_obj = sd->parent_obj; 
+        child_obj = sd->obj;
+        sd = evas_object_smart_data_get(parent_obj);
+
+        if ((!parent_obj) || (!sd) || (!_elm_widget_is(parent_obj))) break;
+
+        evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
+        evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
+
+        x += (cx - px);
+        y += (cy - py);
+        sd->rx = x;
+        sd->ry = y;
+        sd->rw = w;
+        sd->rh = h;
+
+        if (sd->on_show_region_func)
+          {
+             sd->on_show_region_func(sd->on_show_region_data, parent_obj);
+          }
+     }
+   while (parent_obj);
+}
+
+EAPI void
+elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   API_ENTRY return;
+   if (x) *x = sd->rx;
+   if (y) *y = sd->ry;
+   if (w) *w = sd->rw;
+   if (h) *h = sd->rh;
+}
+
+/**
+ * @internal
+ *
+ * Get the focus region of the given widget.
+ *
+ * The focus region is the area of a widget that should brought into the
+ * visible area when the widget is focused. Mostly used to show the part of
+ * an entry where the cursor is, for example. The area returned is relative
+ * to the object @p obj.
+ * If the @p obj doesn't have the proper on_focus_region_hook set, this
+ * function will return the full size of the object.
+ *
+ * @param obj The widget object
+ * @param x Where to store the x coordinate of the area
+ * @param y Where to store the y coordinate of the area
+ * @param w Where to store the width of the area
+ * @param h Where to store the height of the area
+ *
+ * @ingroup Widget
+ */
+EAPI void
+elm_widget_focus_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   Smart_Data *sd;
+
+   if (!obj) return;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
+     {
+        evas_object_geometry_get(obj, NULL, NULL, w, h);
+        if (x) *x = 0;
+        if (y) *y = 0;
+        return;
+     }
+   sd->on_focus_region_func(obj, x, y, w, h);
+}
+
+EAPI void
+elm_widget_scroll_hold_push(Evas_Object *obj)
+{
+   API_ENTRY return;
+   sd->scroll_hold++;
+   if (sd->scroll_hold == 1)
+      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
+   if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
+   // FIXME: on delete/reparent hold pop
+}
+
+EAPI void
+elm_widget_scroll_hold_pop(Evas_Object *obj)
+{
+   API_ENTRY return;
+   sd->scroll_hold--;
+   if (sd->scroll_hold < 0) sd->scroll_hold = 0;
+   if (!sd->scroll_hold)
+      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
+   if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
+}
+
+EAPI int
+elm_widget_scroll_hold_get(const Evas_Object *obj)
+{
+   API_ENTRY return 0;
+   return sd->scroll_hold;
+}
+
+EAPI void
+elm_widget_scroll_freeze_push(Evas_Object *obj)
+{
+   API_ENTRY return;
+   sd->scroll_freeze++;
+   if (sd->scroll_freeze == 1)
+      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
+   if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
+   // FIXME: on delete/reparent freeze pop
+}
+
+EAPI void
+elm_widget_scroll_freeze_pop(Evas_Object *obj)
+{
+   API_ENTRY return;
+   sd->scroll_freeze--;
+   if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
+   if (!sd->scroll_freeze)
+      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
+   if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
+}
+
+EAPI int
+elm_widget_scroll_freeze_get(const Evas_Object *obj)
+{
+   API_ENTRY return 0;
+   return sd->scroll_freeze;
+}
+
+EAPI void
+elm_widget_scale_set(Evas_Object *obj, double scale)
+{
+   API_ENTRY return;
+   if (scale <= 0.0) scale = 0.0;
+   if (sd->scale != scale)
+     {
+       sd->scale = scale;
+       elm_widget_theme(obj);
+     }
+}
+
+EAPI double
+elm_widget_scale_get(const Evas_Object *obj)
+{
+   API_ENTRY return 1.0;
+   // FIXME: save walking up the tree by storing/caching parent scale
+   if (sd->scale == 0.0)
+     {
+       if (sd->parent_obj)
+           return elm_widget_scale_get(sd->parent_obj);
+       else
+           return 1.0;
+     }
+   return sd->scale;
+}
+
+EAPI void
+elm_widget_theme_set(Evas_Object *obj, Elm_Theme *th)
+{
+   API_ENTRY return;
+   if (sd->theme != th)
+     {
+        if (sd->theme) elm_theme_free(sd->theme);
+        sd->theme = th;
+        if (th) th->ref++;
+        elm_widget_theme(obj);
+     }
+}
+
+EAPI Elm_Theme *
+elm_widget_theme_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   if (!sd->theme)
+     {
+        if (sd->parent_obj)
+           return elm_widget_theme_get(sd->parent_obj);
+        else
+           return NULL;
+     }
+   return sd->theme;
+}
+
+EAPI void
+elm_widget_style_set(Evas_Object *obj, const char *style)
+{
+   API_ENTRY return;
+   
+   if (eina_stringshare_replace(&sd->style, style))
+      elm_widget_theme(obj);
+}
+
+EAPI const char *
+elm_widget_style_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   if (sd->style) return sd->style;
+   return "default";
+}
+
+EAPI void
+elm_widget_type_set(Evas_Object *obj, const char *type)
+{
+   API_ENTRY return;
+   eina_stringshare_replace(&sd->type, type);
+}
+
+EAPI const char *
+elm_widget_type_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   if (sd->type) return sd->type;
+   return "";
+}
+
+EAPI void
+elm_widget_tooltip_add(Evas_Object *obj, Elm_Tooltip *tt)
+{
+   API_ENTRY return;
+   sd->tooltips = eina_list_append(sd->tooltips, tt);
+}
+
+EAPI void
+elm_widget_tooltip_del(Evas_Object *obj, Elm_Tooltip *tt)
+{
+   API_ENTRY return;
+   sd->tooltips = eina_list_remove(sd->tooltips, tt);
+}
+
+EAPI void
+elm_widget_cursor_add(Evas_Object *obj, Elm_Cursor *cur)
+{
+   API_ENTRY return;
+   sd->cursors = eina_list_append(sd->cursors, cur);
+}
+
+EAPI void
+elm_widget_cursor_del(Evas_Object *obj, Elm_Cursor *cur)
+{
+   API_ENTRY return;
+   sd->cursors = eina_list_remove(sd->cursors, cur);
+}
+
+EAPI void
+elm_widget_drag_lock_x_set(Evas_Object *obj, Eina_Bool lock)
+{
+   API_ENTRY return;
+   if (sd->drag_x_locked == lock) return;
+   sd->drag_x_locked = lock;
+   if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
+   else _propagate_x_drag_lock(obj, -1);
+}
+
+EAPI void
+elm_widget_drag_lock_y_set(Evas_Object *obj, Eina_Bool lock)
+{
+   API_ENTRY return;
+   if (sd->drag_y_locked == lock) return;
+   sd->drag_y_locked = lock;
+   if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
+   else _propagate_y_drag_lock(obj, -1);
+}
+
+EAPI Eina_Bool
+elm_widget_drag_lock_x_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->drag_x_locked;
+}
+
+EAPI Eina_Bool
+elm_widget_drag_lock_y_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->drag_y_locked;
+}
+
+EAPI int
+elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
+{
+   API_ENTRY return 0;
+   return sd->child_drag_x_locked;
+}
+
+EAPI int
+elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
+{
+   API_ENTRY return 0;
+   return sd->child_drag_y_locked;
+}
+
+EAPI Eina_Bool
+elm_widget_theme_object_set(Evas_Object *obj, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle)
+{
+   API_ENTRY return EINA_FALSE;
+   return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
+}
+
+EAPI Eina_Bool
+elm_widget_type_check(const Evas_Object *obj, const char *type)
+{
+   const char *provided, *expected = "(unknown)";
+   static int abort_on_warn = -1;
+   provided = elm_widget_type_get(obj);
+   if (EINA_LIKELY(provided == type)) return EINA_TRUE;
+   if (type) expected = type;
+   if ((!provided) || (!provided[0]))
+     {
+        provided = evas_object_type_get(obj);
+        if ((!provided) || (!provided[0]))
+           provided = "(unknown)";
+     }
+   ERR("Passing Object: %p, of type: '%s' when expecting type: '%s'", obj, provided, expected);
+   if (abort_on_warn == -1)
+     {
+        if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
+        else abort_on_warn = 0;
+     }
+   if (abort_on_warn == 1) abort();
+   return EINA_FALSE;
+}
+
+/**
+ * @internal
+ *
+ * Split string in words
+ *
+ * @param str Source string
+ * @return List of const words
+ *
+ * @see elm_widget_stringlist_free()
+ * @ingroup Widget
+ */
+EAPI Eina_List *
+elm_widget_stringlist_get(const char *str)
+{
+   Eina_List *list = NULL;
+   const char *s, *b;
+   if (!str) return NULL;
+   for (b = s = str; 1; s++)
+     {
+       if ((*s == ' ') || (!*s))
+         {
+            char *t = malloc(s - b + 1);
+            if (t)
+              {
+                 strncpy(t, b, s - b);
+                 t[s - b] = 0;
+                 list = eina_list_append(list, eina_stringshare_add(t));
+                 free(t);
+              }
+            b = s + 1;
+         }
+       if (!*s) break;
+     }
+   return list;
+}
+
+EAPI void
+elm_widget_stringlist_free(Eina_List *list)
+{
+   const char *s;
+   EINA_LIST_FREE(list, s) eina_stringshare_del(s);
+}
+
+/**
+ * @internal
+ *
+ * Allocate a new Elm_Widget_Item-derived structure.
+ *
+ * The goal of this structure is to provide common ground for actions
+ * that a widget item have, such as the owner widget, callback to
+ * notify deletion, data pointer and maybe more.
+ *
+ * @param widget the owner widget that holds this item, must be an elm_widget!
+ * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
+ *        be used to allocate memory.
+ *
+ * @return allocated memory that is already zeroed out, or NULL on errors.
+ *
+ * @see elm_widget_item_new() convenience macro.
+ * @see elm_widget_item_del() to release memory.
+ * @ingroup Widget
+ */
+EAPI Elm_Widget_Item *
+_elm_widget_item_new(Evas_Object *widget, size_t alloc_size)
+{
+   if (!_elm_widget_is(widget))
+     return NULL;
+
+   Elm_Widget_Item *item;
+
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
+
+   item = calloc(1, alloc_size);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
+
+   EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
+   item->widget = widget;
+   return item;
+}
+
+/**
+ * @internal
+ *
+ * Releases widget item memory, calling back del_cb() if it exists.
+ *
+ * If there is a Elm_Widget_Item::del_cb, then it will be called prior
+ * to memory release. Note that elm_widget_item_pre_notify_del() calls
+ * this function and then unset it, thus being useful for 2 step
+ * cleanup whenever the del_cb may use any of the data that must be
+ * deleted from item.
+ *
+ * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
+ * is presented!
+ *
+ * @param item a valid #Elm_Widget_Item to be deleted.
+ * @see elm_widget_item_del() convenience macro.
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_del(Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+
+   if (item->del_cb)
+     item->del_cb((void *)item->data, item->widget, item);
+
+   if (item->view)
+     evas_object_del(item->view);
+
+   EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
+   free(item);
+}
+
+/**
+ * @internal
+ *
+ * Notify object will be deleted without actually deleting it.
+ *
+ * This function will callback Elm_Widget_Item::del_cb if it is set
+ * and then unset it so it is not called twice (ie: from
+ * elm_widget_item_del()).
+ *
+ * @param item a valid #Elm_Widget_Item to be notified
+ * @see elm_widget_item_pre_notify_del() convenience macro.
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   if (!item->del_cb) return;
+   item->del_cb((void *)item->data, item->widget, item);
+   item->del_cb = NULL;
+}
+
+/**
+ * @internal
+ *
+ * Set the function to notify when item is being deleted.
+ *
+ * This function will complain if there was a callback set already,
+ * however it will set the new one.
+ *
+ * The callback will be called from elm_widget_item_pre_notify_del()
+ * or elm_widget_item_del() will be called with:
+ *   - data: the Elm_Widget_Item::data value.
+ *   - obj: the Elm_Widget_Item::widget evas object.
+ *   - event_info: the item being deleted.
+ *
+ * @param item a valid #Elm_Widget_Item to be notified
+ * @see elm_widget_item_del_cb_set() convenience macro.
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_del_cb_set(Elm_Widget_Item *item, Evas_Smart_Cb del_cb)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+
+   if ((item->del_cb) && (item->del_cb != del_cb))
+     WRN("You're replacing a previously set del_cb %p of item %p with %p",
+         item->del_cb, item, del_cb);
+
+   item->del_cb = del_cb;
+}
+
+/**
+ * @internal
+ *
+ * Set user-data in this item.
+ *
+ * User data may be used to identify this item or just store any
+ * application data. It is automatically given as the first parameter
+ * of the deletion notify callback.
+ *
+ * @param item a valid #Elm_Widget_Item to store data in.
+ * @param data user data to store.
+ * @see elm_widget_item_del_cb_set() convenience macro.
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_data_set(Elm_Widget_Item *item, const void *data)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   if ((item->data) && (item->data != data))
+     DBG("Replacing item %p data %p with %p", item, item->data, data);
+   item->data = data;
+}
+
+/**
+ * @internal
+ *
+ * Retrieves user-data of this item.
+ *
+ * @param item a valid #Elm_Widget_Item to get data from.
+ * @see elm_widget_item_data_set()
+ * @ingroup Widget
+ */
+EAPI void *
+_elm_widget_item_data_get(const Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
+   return (void *)item->data;
+}
+
+typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
+
+struct _Elm_Widget_Item_Tooltip
+{
+   Elm_Widget_Item             *item;
+   Elm_Tooltip_Item_Content_Cb  func;
+   Evas_Smart_Cb                del_cb;
+   const void                  *data;
+};
+
+static Evas_Object *
+_elm_widget_item_tooltip_label_create(void *data, Evas_Object *obj, void *item __UNUSED__)
+{
+   Evas_Object *label = elm_label_add(obj);
+   if (!label)
+     return NULL;
+   elm_object_style_set(label, "tooltip");
+   elm_label_label_set(label, data);
+   return label;
+}
+
+static void
+_elm_widget_item_tooltip_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   eina_stringshare_del(data);
+}
+
+/**
+ * @internal
+ *
+ * Set the text to be shown in the widget item.
+ *
+ * @param item Target item
+ * @param text The text to set in the content
+ *
+ * Setup the text as tooltip to object. The item can have only one tooltip,
+ * so any previous tooltip data is removed.
+ *
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_tooltip_text_set(Elm_Widget_Item *item, const char *text)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   text = eina_stringshare_add(text);
+   _elm_widget_item_tooltip_content_cb_set
+     (item, _elm_widget_item_tooltip_label_create, text,
+      _elm_widget_item_tooltip_label_del_cb);
+}
+
+static Evas_Object *
+_elm_widget_item_tooltip_create(void *data, Evas_Object *obj)
+{
+   Elm_Widget_Item_Tooltip *wit = data;
+   return wit->func((void *)wit->data, obj, wit->item);
+}
+
+static void
+_elm_widget_item_tooltip_del_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Widget_Item_Tooltip *wit = data;
+   if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
+   free(wit);
+}
+
+/**
+ * @internal
+ *
+ * Set the content to be shown in the tooltip item
+ *
+ * Setup the tooltip to item. The item can have only one tooltip,
+ * so any previous tooltip data is removed. @p func(with @p data) will
+ * be called every time that need show the tooltip and it should
+ * return a valid Evas_Object. This object is then managed fully by
+ * tooltip system and is deleted when the tooltip is gone.
+ *
+ * @param item the widget item being attached a tooltip.
+ * @param func the function used to create the tooltip contents.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_widget_item_tooltip_unset() or the owner @a item
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is the item.
+ *
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
+{
+   Elm_Widget_Item_Tooltip *wit;
+
+   ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
+
+   if (!func)
+     {
+        _elm_widget_item_tooltip_unset(item);
+        return;
+     }
+
+   wit = ELM_NEW(Elm_Widget_Item_Tooltip);
+   if (!wit) goto error;
+   wit->item = item;
+   wit->func = func;
+   wit->data = data;
+   wit->del_cb = del_cb;
+
+   elm_object_sub_tooltip_content_cb_set
+     (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
+      _elm_widget_item_tooltip_del_cb);
+
+   return;
+
+ error_noitem:
+   if (del_cb) del_cb((void *)data, NULL, item);
+   return;
+ error:
+   if (del_cb) del_cb((void *)data, item->widget, item);
+}
+
+/**
+ * @internal
+ *
+ * Unset tooltip from item
+ *
+ * @param item widget item to remove previously set tooltip.
+ *
+ * Remove tooltip from item. The callback provided as del_cb to
+ * elm_widget_item_tooltip_content_cb_set() will be called to notify
+ * it is not used anymore.
+ *
+ * @see elm_widget_item_tooltip_content_cb_set()
+ *
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   elm_object_tooltip_unset(item->view);
+}
+
+/**
+ * @internal
+ *
+ * Sets a different style for this item tooltip.
+ *
+ * @note before you set a style you should define a tooltip with
+ *       elm_widget_item_tooltip_content_cb_set() or
+ *       elm_widget_item_tooltip_text_set()
+ *
+ * @param item widget item with tooltip already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_tooltip_style_set(Elm_Widget_Item *item, const char *style)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   elm_object_tooltip_style_set(item->view, style);
+}
+
+/**
+ * @internal
+ *
+ * Get the style for this item tooltip.
+ *
+ * @param item widget item with tooltip already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a tooltip set, then NULL is returned.
+ *
+ * @ingroup Widget
+ */
+EAPI const char *
+_elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
+   return elm_object_tooltip_style_get(item->view);
+}
+
+EAPI void
+_elm_widget_item_cursor_set(Elm_Widget_Item *item, const char *cursor)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   elm_object_sub_cursor_set(item->view, item->widget, cursor);
+}
+
+EAPI const char *
+_elm_widget_item_cursor_get(const Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
+   return elm_object_cursor_get(item->view);
+}
+
+EAPI void
+_elm_widget_item_cursor_unset(Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   elm_object_cursor_unset(item->view);
+}
+
+/**
+ * @internal
+ *
+ * Sets a different style for this item cursor.
+ *
+ * @note before you set a style you should define a cursor with
+ *       elm_widget_item_cursor_set()
+ *
+ * @param item widget item with cursor already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_cursor_style_set(Elm_Widget_Item *item, const char *style)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   elm_object_cursor_style_set(item->view, style);
+}
+
+/**
+ * @internal
+ *
+ * Get the style for this item cursor.
+ *
+ * @param item widget item with cursor already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup Widget
+ */
+EAPI const char *
+_elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
+   return elm_object_cursor_style_get(item->view);
+}
+
+/**
+ * @internal
+ *
+ * Set if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a cursor
+ * with elm_object_cursor_set(). By default it will only look for cursors
+ * provided by the engine.
+ *
+ * @param item widget item with cursor already set.
+ * @param engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well.
+ *
+ * @ingroup Widget
+ */
+EAPI void
+_elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item, Eina_Bool engine_only)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   elm_object_cursor_engine_only_set(item->view, engine_only);
+}
+
+/**
+ * @internal
+ *
+ * Get the cursor engine only usage for this item cursor.
+ *
+ * @param item widget item with cursor already set.
+ * @return engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well. If
+ *         the object does not have a cursor set, then EINA_FALSE is returned.
+ *
+ * @ingroup Widget
+ */
+EAPI Eina_Bool
+_elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
+   return elm_object_cursor_engine_only_get(item->view);
+}
+
+// smart object funcs
+static void
+_smart_reconfigure(Smart_Data *sd)
+{
+   if (sd->resize_obj)
+     {
+        evas_object_move(sd->resize_obj, sd->x, sd->y);
+       evas_object_resize(sd->resize_obj, sd->w, sd->h);
+     }
+   if (sd->hover_obj)
+     {
+        evas_object_move(sd->hover_obj, sd->x, sd->y);
+       evas_object_resize(sd->hover_obj, sd->w, sd->h);
+     }
+}
+
+static void
+_smart_add(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = calloc(1, sizeof(Smart_Data));
+   if (!sd) return;
+   sd->obj = obj;
+   sd->x = sd->y = sd->w = sd->h = 0;
+   sd->can_focus = 1;
+   evas_object_smart_data_set(obj, sd);
+}
+
+static Evas_Object *
+_newest_focus_order_get(Evas_Object *obj, unsigned int *newest_focus_order, Eina_Bool can_focus_only)
+{
+   const Eina_List *l;
+   Evas_Object *child, *ret, *best;
+   
+   API_ENTRY return NULL;
+   if (!evas_object_visible_get(obj)) return NULL;
+   best = NULL;
+   if (*newest_focus_order < sd->focus_order)
+     {
+        *newest_focus_order = sd->focus_order;
+        best = obj;
+     }
+   EINA_LIST_FOREACH(sd->subobjs, l, child)
+     {
+        ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
+        if (!ret) continue;
+        best = ret;
+     }
+   if ((can_focus_only) && (!elm_widget_can_focus_get(best))) return NULL;
+   return best;
+}
+
+static void
+_if_focused_revert(Evas_Object *obj, Eina_Bool can_focus_only)
+{
+   Evas_Object *top;
+   Evas_Object *newest = NULL;
+   unsigned int newest_focus_order = 0;
+   
+   INTERNAL_ENTRY;
+
+   if (!sd->focused) return;
+   if (!sd->parent_obj) return;
+
+   top = elm_widget_top_get(sd->parent_obj);
+   if (top)
+     {
+        newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
+        if (newest)
+          {
+             elm_object_unfocus(newest);
+             elm_object_focus(newest);
+          }
+     }
+}
+
+static void
+_smart_del(Evas_Object *obj)
+{
+   Evas_Object *sobj;
+   Edje_Signal_Data *esd;
+
+   INTERNAL_ENTRY;
+
+   if (sd->del_pre_func) sd->del_pre_func(obj);
+   if (sd->resize_obj)
+     {
+       sobj = sd->resize_obj;
+       sd->resize_obj = NULL;
+       evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
+       evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
+       evas_object_del(sobj);
+     }
+   if (sd->hover_obj)
+     {
+       sobj = sd->hover_obj;
+       sd->hover_obj = NULL;
+       evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
+       evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
+       evas_object_del(sobj);
+     }
+   EINA_LIST_FREE(sd->subobjs, sobj)
+     {
+       evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
+       evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
+       evas_object_del(sobj);
+     }
+   eina_list_free(sd->tooltips); /* should be empty anyway */
+   eina_list_free(sd->cursors); /* should be empty anyway */
+   EINA_LIST_FREE(sd->edje_signals, esd)
+     {
+        eina_stringshare_del(esd->emission);
+        eina_stringshare_del(esd->source);
+        free(esd);
+     }
+   eina_list_free(sd->event_cb); /* should be empty anyway */
+   if (sd->del_func) sd->del_func(obj);
+   if (sd->style) eina_stringshare_del(sd->style);
+   if (sd->type) eina_stringshare_del(sd->type);
+   if (sd->theme) elm_theme_free(sd->theme);
+   _if_focused_revert(obj, EINA_TRUE);
+   free(sd);
+}
+
+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)
+{
+   Eina_List *list;
+   Evas_Object *o;
+   INTERNAL_ENTRY;
+   if ((list = evas_object_smart_members_get(obj)))
+     {
+        EINA_LIST_FREE(list, o)
+          {
+             if (evas_object_data_get(o, "_elm_leaveme")) continue;
+             evas_object_show(o);
+          }
+     }
+}
+
+static void
+_smart_hide(Evas_Object *obj)
+{
+   Eina_List *list;
+   Evas_Object *o;
+   INTERNAL_ENTRY;
+   list = evas_object_smart_members_get(obj);
+   EINA_LIST_FREE(list, o)
+     {
+        if (evas_object_data_get(o, "_elm_leaveme")) continue;
+        evas_object_hide(o);
+     }
+   _if_focused_revert(obj, EINA_TRUE);
+}
+
+static void
+_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
+{
+   Eina_List *list;
+   Evas_Object *o;
+   INTERNAL_ENTRY;
+   if ((list = evas_object_smart_members_get(obj)))
+     {
+        EINA_LIST_FREE(list, o)
+          {
+             if (evas_object_data_get(o, "_elm_leaveme")) continue;
+             evas_object_color_set(o, r, g, b, a);
+          }
+     }
+}
+
+static void
+_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
+{
+   Eina_List *list;
+   Evas_Object *o;
+   INTERNAL_ENTRY;
+   if ((list = evas_object_smart_members_get(obj)))
+     {
+        EINA_LIST_FREE(list, o)
+          {
+             if (evas_object_data_get(o, "_elm_leaveme")) continue;
+             evas_object_clip_set(o, clip);
+          }
+     }
+}
+
+static void
+_smart_clip_unset(Evas_Object *obj)
+{
+   Eina_List *list;
+   Evas_Object *o;
+   INTERNAL_ENTRY;
+   if ((list = evas_object_smart_members_get(obj)))
+     {
+        EINA_LIST_FREE(list, o)
+          {
+             if (evas_object_data_get(o, "_elm_leaveme")) continue;
+             evas_object_clip_unset(o);
+          }
+     }
+}
+
+static void
+_smart_calculate(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   if (sd->changed_func) sd->changed_func(obj);
+}
+
+/* never need to touch this */
+static void
+_smart_init(void)
+{
+   if (_e_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,
+             _smart_calculate,
+             NULL,
+             NULL,
+             NULL,
+             NULL,
+             NULL,
+             NULL
+         };
+       _e_smart = evas_smart_class_new(&sc);
+     }
+}
+
+/* happy debug functions */
+#ifdef ELM_DEBUG
+static void
+_sub_obj_tree_dump(const Evas_Object *o, int lvl)
+{
+   int i;
+
+   for (i = 0; i < lvl*3; i++)
+     putchar(' ');
+
+   if (_elm_widget_is(o))
+     {
+        Eina_List *l;
+        Smart_Data *sd = evas_object_smart_data_get(o);
+        printf("+ %s(%p)\n", sd->type, o);
+        if (sd->resize_obj)
+          _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
+        EINA_LIST_FOREACH(sd->subobjs, l, o)
+          {
+             if (o != sd->resize_obj)
+               _sub_obj_tree_dump(o, lvl + 1);
+          }
+     }
+   else
+     printf("+ %s(%p)\n", evas_object_type_get(o), o);
+}
+
+static void
+_sub_obj_tree_dot_dump(const Evas_Object *obj, FILE *output)
+{
+   if (!_elm_widget_is(obj))
+     return;
+
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+
+   Eina_Bool visible = evas_object_visible_get(obj);
+   Eina_Bool disabled = elm_widget_disabled_get(obj);
+   Eina_Bool focused = elm_widget_focus_get(obj);
+   Eina_Bool can_focus = elm_widget_can_focus_get(obj);
+
+   if (sd->parent_obj)
+     {
+        fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
+
+        if (focused)
+          fprintf(output, ", style=bold");
+
+        if (!visible)
+          fprintf(output, ", color=gray28");
+
+        fprintf(output, " ];\n");
+     }
+
+   fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
+           "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
+           evas_object_name_get(obj), visible, disabled, focused, can_focus,
+           sd->focus_order);
+
+   if (focused)
+        fprintf(output, ", style=bold");
+
+   if (!visible)
+        fprintf(output, ", fontcolor=gray28");
+
+   if ((disabled) || (!visible))
+        fprintf(output, ", color=gray");
+
+
+   fprintf(output, " ];\n");
+
+   Eina_List *l;
+   Evas_Object *o;
+   EINA_LIST_FOREACH(sd->subobjs, l, o)
+      _sub_obj_tree_dot_dump(o, output);
+}
+#endif
+
+EAPI void
+elm_widget_tree_dump(const Evas_Object *top)
+{
+#ifdef ELM_DEBUG
+   _sub_obj_tree_dump(top, 0);
+#else
+   return;
+   (void)top;
+#endif
+}
+
+EAPI void
+elm_widget_tree_dot_dump(const Evas_Object *top, FILE *output)
+{
+#ifdef ELM_DEBUG
+   if (!_elm_widget_is(top))
+     return;
+   fprintf(output, "graph "" { node [shape=record];\n");
+   _sub_obj_tree_dot_dump(top, output);
+   fprintf(output, "}\n");
+#else
+   return;
+   (void)top;
+   (void)output;
+#endif
+}
diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h
new file mode 100644 (file)
index 0000000..bb25156
--- /dev/null
@@ -0,0 +1,545 @@
+#ifndef ELM_WIDGET_H
+#define ELM_WIDGET_H
+
+/* DO NOT USE THIS HEADER UNLESS YOU ARE PREPARED FOR BREAKING OF YOUR
+ * CODE. THIS IS ELEMENTARY'S INTERNAL WIDGET API (for now) AND IS NOT
+ * FINAL. CALL elm_widget_api_check(ELM_INTERNAL_API_VERSION) TO CHECK IT
+ * AT RUNTIME
+ * 
+ * How to make your own widget? like this:
+ * 
+ * #include <Elementary.h>
+ * #include "elm_priv.h"
+ * 
+ * typedef struct _Widget_Data Widget_Data;
+ *    
+ * struct _Widget_Data
+ * {
+ *   Evas_Object *sub;
+ *   // add any other widget data here too
+ * };
+ * 
+ * static const char *widtype = NULL;
+ * 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 _on_focus_hook(void *data, Evas_Object *obj);
+ * 
+ * static const char SIG_CLICKED[] = "clicked";
+ * static const Evas_Smart_Cb_Description _signals[] = {
+ *   {SIG_CLICKED, ""},
+ *   {NULL, NULL}
+ * };
+ * 
+ * static void
+ * _del_hook(Evas_Object *obj)
+ * {
+ *    Widget_Data *wd = elm_widget_data_get(obj);
+ *    if (!wd) return;
+ *    // delete hook - on delete of object delete object struct etc.
+ *    free(wd);
+ * }
+ * 
+ * static void
+ * _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
+ * {
+ *    Widget_Data *wd = elm_widget_data_get(obj);
+ *    if (!wd) return;
+ *    // handle focus going in and out - optional, but if you want to, set
+ *    // this hook and handle it (eg emit a signal to an edje obj)
+ *    if (elm_widget_focus_get(obj))
+ *      {
+ *         edje_object_signal_emit(wd->sub, "elm,action,focus", "elm");
+ *         evas_object_focus_set(wd->sub, EINA_TRUE);
+ *      }
+ *    else
+ *      {
+ *         edje_object_signal_emit(wd->sub, "elm,action,unfocus", "elm");
+ *         evas_object_focus_set(wd->sub, EINA_FALSE);
+ *      }
+ * }
+ * 
+ * static void
+ * _theme_hook(Evas_Object *obj)
+ * {
+ *    Widget_Data *wd = elm_widget_data_get(obj);
+ *    if (!wd) return;
+ *    // handle change in theme/scale etc.
+ *    elm_widget_theme_object_set(obj, wd->sub, "mywidget", "base", 
+ *                                elm_widget_style_get(obj));
+ * }
+ * 
+ * static void
+ * _disable_hook(Evas_Object *obj)
+ * {
+ *    Widget_Data *wd = elm_widget_data_get(obj);
+ *    if (!wd) return;
+ *    // optional, but handle if the widget gets disabled or not
+ *    if (elm_widget_disabled_get(obj))
+ *      edje_object_signal_emit(wd->sub, "elm,state,disabled", "elm");
+ *    else
+ *      edje_object_signal_emit(wd->sub, "elm,state,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;
+ *    if (!wd) return;
+ *    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+ *    edje_object_size_min_restricted_calc(wd->sub, &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);
+ * }
+ * 
+ * // actual api to create your widget. add more to manipulate it as needed
+ * // mark your calls with EAPI to make them "external api" calls.
+ * EAPI Evas_Object *
+ * elm_mywidget_add(Evas_Object *parent)
+ * {
+ *    Evas_Object *obj;
+ *    Evas *e;
+ *    Widget_Data *wd;
+ * 
+ *    // ALWAYS call this - this checks that your widget matches that of
+ *    // elementary and that the api hasn't broken. if it has this returns
+ *    // false and you need to handle this error gracefully
+ *    if (!elm_widget_api_check(ELM_INTERNAL_API_VERSION)) return NULL;
+ * 
+ *    // basic - allocate data for widget and fill it
+ *    wd = ELM_NEW(Widget_Data);
+ *    e = evas_object_evas_get(parent);
+ *    if (!e) return NULL;
+ *    obj = elm_widget_add(e);
+ *    // give it a type name and set up a mywidget type string if needed
+ *    ELM_SET_WIDTYPE(widtype, "mywidget");
+ *    elm_widget_type_set(obj, "mywidget");
+ *    // tell the parent widget that we are a sub object
+ *    elm_widget_sub_object_add(parent, obj);
+ *    // setup hooks we need (some are optional)
+ *    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_theme_hook_set(obj, _theme_hook);
+ *    elm_widget_disable_hook_set(obj, _disable_hook);
+ *    // this widget can focus (true means yes it can, false means it can't)
+ *    elm_widget_can_focus_set(obj, EINA_TRUE);
+ * 
+ *    // for this widget we will add 1 sub object that is an edje object
+ *    wd->sub = edje_object_add(e);
+ *    // set the theme. this follows a scheme for group name like this:
+ *    //   "elm/WIDGETNAME/ELEMENT/STYLE"
+ *    // so here it will be:
+ *    //   "elm/mywidget/base/default"
+ *    // changing style changes style name from default (all widgets start
+ *    // with the default style) and element is for your widget internal
+ *    // structure as you see fit
+ *    elm_widget_theme_object_set(obj, wd->sub, "mywidget", "base", "default");
+ *    // listen to a signal from the edje object to produce widget smart
+ *    // callback (like click)
+ *    edje_object_signal_callback_add(wd->sub, "elm,action,click", "",
+ *                                    _signal_clicked, obj);
+ *    // set this sub object as the "resize object". widgets get 1 resize
+ *    // object that is resized along with the object wrapper.
+ *    elm_widget_resize_object_set(obj, wd->sub);
+ * 
+ *    // evaluate sizing of the widget (minimum size calc etc.). optional but
+ *    // not a bad idea to do here. it will get queued for later anyway
+ *    _sizing_eval(obj);
+ * 
+ *    // register the smart callback descriptions so we can have some runtime
+ *    // info as to what the smart callback strings mean
+ *    evas_object_smart_callbacks_descriptions_set(obj, _signals);
+ *    return obj;
+ * }
+ * 
+ * // example - do "whatever" to the widget (here just emit a signal)
+ * EAPI void
+ * elm_mywidget_whatever(Evas_Object *obj)
+ * {
+ *    // check if type is correct - check will return if it fails
+ *    ELM_CHECK_WIDTYPE(obj, widtype);
+ *    // get widget data - type is correct and sane by this point, so this
+ *    // should never fail
+ *    Widget_Data *wd = elm_widget_data_get(obj);
+ *    // do whatever you like
+ *    edje_object_signal_emit(wd->sub, "elm,state,action,whatever", "elm");
+ * }
+ * 
+ * // you can add more - you need to see elementary's code to know how to
+ * // handle all cases. remember this api is not stable and may change. it's
+ * // internal
+ * 
+ */
+
+#ifndef ELM_INTERAL_API_MDFGELQ
+# warning "You are using an internal elementary API. This API is not stable"
+# warning "and is subject to change. You use this at your own risk."
+# warning "Remember to call elm_widget_api_check(ELM_INTERNAL_API_VERSION);"
+# warning "in your widgets before you call any other elm_widget calls to do"
+# warning "a correct runtime version check."
+#endif
+#define ELM_INTERNAL_API_VERSION 7000
+
+typedef struct _Elm_Tooltip Elm_Tooltip;
+typedef struct _Elm_Cursor Elm_Cursor;
+typedef struct _Elm_Widget_Item Elm_Widget_Item; /**< base structure for all widget items that are not Elm_Widget themselves */
+
+struct _Elm_Widget_Item
+{
+   /* ef1 ~~ efl, el3 ~~ elm */
+#define ELM_WIDGET_ITEM_MAGIC 0xef1e1301
+   EINA_MAGIC;
+   
+   Evas_Object   *widget; /**< the owner widget that owns this item */
+   Evas_Object   *view; /**< the base view object */
+   const void    *data; /**< item specific data */
+   Evas_Smart_Cb  del_cb; /**< used to notify the item is being deleted */
+   /* widget variations should have data from here and on */
+   /* @todo: TODO check if this is enough for 1.0 release, maybe add padding! */
+};
+
+#define ELM_NEW(t) calloc(1, sizeof(t))
+
+EAPI Eina_Bool        elm_widget_api_check(int ver);
+EAPI Evas_Object     *elm_widget_add(Evas *evas);
+EAPI void             elm_widget_del_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_del_pre_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_focus_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_activate_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_disable_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_theme_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_event_hook_set(Evas_Object *obj, Eina_Bool (*func) (Evas_Object *obj, Evas_Object *source, Evas_Callback_Type type, void *event_info));
+EAPI void             elm_widget_changed_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_signal_emit_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source));
+EAPI void             elm_widget_signal_callback_add_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data));
+EAPI void             elm_widget_signal_callback_del_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data));
+EAPI void             elm_widget_theme(Evas_Object *obj);
+EAPI void             elm_widget_theme_specific(Evas_Object *obj, Elm_Theme *th, Eina_Bool force);
+EAPI void             elm_widget_focus_next_hook_set(Evas_Object *obj, Eina_Bool (*func) (const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next));
+EAPI void             elm_widget_on_focus_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
+EAPI void             elm_widget_on_change_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
+EAPI void             elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
+EAPI void             elm_widget_focus_region_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h));
+EAPI void             elm_widget_on_focus_region_hook_set(Evas_Object *obj, void (*func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h));
+EAPI void             elm_widget_data_set(Evas_Object *obj, void *data);
+EAPI void            *elm_widget_data_get(const Evas_Object *obj);
+EAPI void             elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj);
+EAPI void             elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj);
+EAPI void             elm_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj);
+EAPI void             elm_widget_hover_object_set(Evas_Object *obj, Evas_Object *sobj);
+EAPI void             elm_widget_signal_emit(Evas_Object *obj, const char *emission, const char *source);
+EAPI void             elm_widget_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data);
+EAPI void            *elm_widget_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source));
+EAPI void             elm_widget_can_focus_set(Evas_Object *obj, Eina_Bool can_focus);
+EAPI Eina_Bool        elm_widget_can_focus_get(const Evas_Object *obj);
+EAPI Eina_Bool        elm_widget_child_can_focus_get(const Evas_Object *obj);
+EAPI void             elm_widget_highlight_ignore_set(Evas_Object *obj, Eina_Bool ignore);
+EAPI Eina_Bool        elm_widget_highlight_ignore_get(const Evas_Object *obj);
+EAPI void             elm_widget_highlight_in_theme_set(Evas_Object *obj, Eina_Bool highlight);
+EAPI Eina_Bool        elm_widget_highlight_in_theme_get(const Evas_Object *obj);
+EAPI Eina_Bool        elm_widget_focus_get(const Evas_Object *obj);
+EAPI Evas_Object     *elm_widget_focused_object_get(const Evas_Object *obj);
+EAPI Evas_Object     *elm_widget_top_get(const Evas_Object *obj);
+EAPI Eina_Bool        elm_widget_is(const Evas_Object *obj);
+EAPI Evas_Object     *elm_widget_parent_widget_get(const Evas_Object *obj);
+EAPI void             elm_widget_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data);
+EAPI void            *elm_widget_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data);
+EAPI Eina_Bool        elm_widget_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags);
+EAPI void             elm_widget_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs);
+EAPI void             elm_widget_focus_custom_chain_unset(Evas_Object *obj);
+EAPI const Eina_List *elm_widget_focus_custom_chain_get(const Evas_Object *obj);
+EAPI void             elm_widget_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
+EAPI void             elm_widget_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
+EAPI void             elm_widget_focus_cycle(Evas_Object *obj, Elm_Focus_Direction dir);
+EAPI void             elm_widget_focus_direction_go(Evas_Object *obj, int x, int y);
+EAPI Eina_Bool        elm_widget_focus_next_get(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next);
+EAPI Eina_Bool        elm_widget_focus_list_next_get(const Evas_Object *obj, const Eina_List *items, void *(*list_data_get) (const Eina_List *list), Elm_Focus_Direction dir, Evas_Object **next);
+EAPI void             elm_widget_focus_set(Evas_Object *obj, int first);
+EAPI void             elm_widget_focused_object_clear(Evas_Object *obj);
+EAPI Evas_Object     *elm_widget_parent_get(const Evas_Object *obj);
+EAPI void             elm_widget_focus_steal(Evas_Object *obj);
+EAPI void             elm_widget_activate(Evas_Object *obj);
+EAPI void             elm_widget_change(Evas_Object *obj);
+EAPI void             elm_widget_disabled_set(Evas_Object *obj, int disabled);
+EAPI int              elm_widget_disabled_get(const Evas_Object *obj);
+EAPI void             elm_widget_show_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+EAPI void             elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+EAPI void             elm_widget_focus_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+EAPI void             elm_widget_scroll_hold_push(Evas_Object *obj);
+EAPI void             elm_widget_scroll_hold_pop(Evas_Object *obj);
+EAPI int              elm_widget_scroll_hold_get(const Evas_Object *obj);
+EAPI void             elm_widget_scroll_freeze_push(Evas_Object *obj);
+EAPI void             elm_widget_scroll_freeze_pop(Evas_Object *obj);
+EAPI int              elm_widget_scroll_freeze_get(const Evas_Object *obj);
+EAPI void             elm_widget_scale_set(Evas_Object *obj, double scale);
+EAPI double           elm_widget_scale_get(const Evas_Object *obj);
+EAPI void             elm_widget_theme_set(Evas_Object *obj, Elm_Theme *th);
+EAPI Elm_Theme       *elm_widget_theme_get(const Evas_Object *obj);
+EAPI void             elm_widget_style_set(Evas_Object *obj, const char *style);
+EAPI const char      *elm_widget_style_get(const Evas_Object *obj);
+EAPI void             elm_widget_type_set(Evas_Object *obj, const char *type);
+EAPI const char      *elm_widget_type_get(const Evas_Object *obj);
+EAPI void             elm_widget_tooltip_add(Evas_Object *obj, Elm_Tooltip *tt);
+EAPI void             elm_widget_tooltip_del(Evas_Object *obj, Elm_Tooltip *tt);
+EAPI void             elm_widget_cursor_add(Evas_Object *obj, Elm_Cursor *cur);
+EAPI void             elm_widget_cursor_del(Evas_Object *obj, Elm_Cursor *cur);
+EAPI void             elm_widget_drag_lock_x_set(Evas_Object *obj, Eina_Bool lock);
+EAPI void             elm_widget_drag_lock_y_set(Evas_Object *obj, Eina_Bool lock);
+EAPI Eina_Bool        elm_widget_drag_lock_x_get(const Evas_Object *obj);
+EAPI Eina_Bool        elm_widget_drag_lock_y_get(const Evas_Object *obj);
+EAPI int              elm_widget_drag_child_locked_x_get(const Evas_Object *obj);
+EAPI int              elm_widget_drag_child_locked_y_get(const Evas_Object *obj);
+EAPI Eina_Bool        elm_widget_theme_object_set(Evas_Object *obj, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle);
+EAPI void             elm_widget_type_register(const char **ptr);
+EAPI Eina_Bool        elm_widget_type_check(const Evas_Object *obj, const char *type);
+EAPI Eina_List       *elm_widget_stringlist_get(const char *str);
+EAPI void             elm_widget_stringlist_free(Eina_List *list);
+
+EAPI Elm_Widget_Item *_elm_widget_item_new(Evas_Object *parent, size_t alloc_size);
+EAPI void             _elm_widget_item_del(Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_pre_notify_del(Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_del_cb_set(Elm_Widget_Item *item, Evas_Smart_Cb del_cb);
+EAPI void             _elm_widget_item_data_set(Elm_Widget_Item *item, const void *data);
+EAPI void            *_elm_widget_item_data_get(const Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item, const char *text);
+EAPI void             _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);
+EAPI void             _elm_widget_item_tooltip_unset(Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item, const char *style);
+EAPI const char      *_elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_cursor_set(Elm_Widget_Item *item, const char *cursor);
+EAPI const char      *_elm_widget_item_cursor_get(const Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_cursor_unset(Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_cursor_style_set(Elm_Widget_Item *item, const char *style);
+EAPI const char      *_elm_widget_item_cursor_style_get(const Elm_Widget_Item *item);
+EAPI void             _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item, Eina_Bool engine_only);
+EAPI Eina_Bool        _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item);
+
+/* debug function. don't use it unless you are tracking parenting issues */
+EAPI void             elm_widget_tree_dump(const Evas_Object *top);
+EAPI void             elm_widget_tree_dot_dump(const Evas_Object *top, FILE *output);
+
+/**
+ * Convenience macro to create new widget item, doing casts for you.
+ * @see _elm_widget_item_new()
+ * @param parent a valid elm_widget variant.
+ * @param type the C type that extends Elm_Widget_Item
+ */
+#define elm_widget_item_new(parent, type) \
+  (type *)_elm_widget_item_new((parent), sizeof(type))
+/**
+ * Convenience macro to delete widget item, doing casts for you.
+ * @see _elm_widget_item_del()
+ * @param item a valid item.
+ */
+#define elm_widget_item_del(item) \
+  _elm_widget_item_del((Elm_Widget_Item *)item)
+/**
+ * Convenience macro to notify deletion of widget item, doing casts for you.
+ * @see _elm_widget_item_pre_notify_del()
+ */
+#define elm_widget_item_pre_notify_del(item) \
+  _elm_widget_item_pre_notify_del((Elm_Widget_Item *)item)
+/**
+ * Convenience macro to set deletion callback of widget item, doing casts for you.
+ * @see _elm_widget_item_del_cb_set()
+ */
+#define elm_widget_item_del_cb_set(item, del_cb) \
+  _elm_widget_item_del_cb_set((Elm_Widget_Item *)item, del_cb)
+
+/**
+ * Set item's data
+ * @see _elm_widget_item_data_set()
+ */
+#define elm_widget_item_data_set(item, data) \
+  _elm_widget_item_data_set((Elm_Widget_Item *)item, data)
+/**
+ * Get item's data
+ * @see _elm_widget_item_data_get()
+ */
+#define elm_widget_item_data_get(item) \
+  _elm_widget_item_data_get((const Elm_Widget_Item *)item)
+
+/**
+ * Convenience function to set widget item tooltip as a text string.
+ * @see _elm_widget_item_tooltip_text_set()
+ */
+#define elm_widget_item_tooltip_text_set(item, text) \
+  _elm_widget_item_tooltip_text_set((Elm_Widget_Item *)item, text)
+/**
+ * Convenience function to set widget item tooltip.
+ * @see _elm_widget_item_tooltip_content_cb_set()
+ */
+#define elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb) \
+  _elm_widget_item_tooltip_content_cb_set((Elm_Widget_Item *)item, \
+                                          func, data, del_cb)
+/**
+ * Convenience function to unset widget item tooltip.
+ * @see _elm_widget_item_tooltip_unset()
+ */
+#define elm_widget_item_tooltip_unset(item) \
+  _elm_widget_item_tooltip_unset((Elm_Widget_Item *)item)
+/**
+ * Convenience function to change item's tooltip style.
+ * @see _elm_widget_item_tooltip_style_set()
+ */
+#define elm_widget_item_tooltip_style_set(item, style) \
+  _elm_widget_item_tooltip_style_set((Elm_Widget_Item *)item, style)
+/**
+ * Convenience function to query item's tooltip style.
+ * @see _elm_widget_item_tooltip_style_get()
+ */
+#define elm_widget_item_tooltip_style_get(item) \
+  _elm_widget_item_tooltip_style_get((const Elm_Widget_Item *)item)
+/**
+ * Convenience function to set widget item cursor.
+ * @see _elm_widget_item_cursor_set()
+ */
+#define elm_widget_item_cursor_set(item, cursor) \
+  _elm_widget_item_cursor_set((Elm_Widget_Item *)item, cursor)
+/**
+ * Convenience function to get widget item cursor.
+ * @see _elm_widget_item_cursor_get()
+ */
+#define elm_widget_item_cursor_get(item) \
+  _elm_widget_item_cursor_get((const Elm_Widget_Item *)item)
+/**
+ * Convenience function to unset widget item cursor.
+ * @see _elm_widget_item_cursor_unset()
+ */
+#define elm_widget_item_cursor_unset(item) \
+  _elm_widget_item_cursor_unset((Elm_Widget_Item *)item)
+/**
+ * Convenience function to change item's cursor style.
+ * @see _elm_widget_item_cursor_style_set()
+ */
+#define elm_widget_item_cursor_style_set(item, style) \
+  _elm_widget_item_cursor_style_set((Elm_Widget_Item *)item, style)
+/**
+ * Convenience function to query item's cursor style.
+ * @see _elm_widget_item_cursor_style_get()
+ */
+#define elm_widget_item_cursor_style_get(item) \
+  _elm_widget_item_cursor_style_get((const Elm_Widget_Item *)item)
+/**
+ * Convenience function to change item's cursor engine_only.
+ * @see _elm_widget_item_cursor_engine_only_set()
+ */
+#define elm_widget_item_cursor_engine_only_set(item, engine_only) \
+  _elm_widget_item_cursor_engine_only_set((Elm_Widget_Item *)item, engine_only)
+/**
+ * Convenience function to query item's cursor engine_only.
+ * @see _elm_widget_item_cursor_engine_only_get()
+ */
+#define elm_widget_item_cursor_engine_only_get(item) \
+  _elm_widget_item_cursor_engine_only_get((const Elm_Widget_Item *)item)
+
+/**
+ * Cast and ensure the given pointer is an Elm_Widget_Item or return NULL.
+ */
+#define ELM_WIDGET_ITEM(item) \
+   (((item) && (EINA_MAGIC_CHECK(item, ELM_WIDGET_ITEM_MAGIC))) ? \
+       ((Elm_Widget_Item *)(item)) : NULL)
+
+#define ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, ...) \
+   do { \
+      if (!item) { \
+         CRITICAL("Elm_Widget_Item " # item " is NULL!"); \
+         return __VA_ARGS__; \
+      } \
+      if (!EINA_MAGIC_CHECK(item, ELM_WIDGET_ITEM_MAGIC)) { \
+         EINA_MAGIC_FAIL(item, ELM_WIDGET_ITEM_MAGIC); \
+         return __VA_ARGS__; \
+      } \
+   } while (0)
+
+#define ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, label) \
+   do { \
+      if (!item) { \
+         CRITICAL("Elm_Widget_Item " # item " is NULL!"); \
+         goto label; \
+      } \
+      if (!EINA_MAGIC_CHECK(item, ELM_WIDGET_ITEM_MAGIC)) { \
+         EINA_MAGIC_FAIL(item, ELM_WIDGET_ITEM_MAGIC); \
+         goto label; \
+      } \
+   } while (0)
+
+#define ELM_SET_WIDTYPE(widtype, type) \
+   do { \
+      if (!widtype) { \
+         widtype = eina_stringshare_add(type); \
+         elm_widget_type_register(&widtype); \
+      } \
+   } while (0)
+
+#define ELM_CHECK_WIDTYPE(obj, widtype) \
+   if (!elm_widget_type_check((obj), (widtype))) return
+
+#define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...)                \
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
+   ELM_CHECK_WIDTYPE(it->base.widget, widtype) __VA_ARGS__;
+
+#define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, label)                \
+   ELM_WIDGET_ITEM_CHECK_OR_GOTO((Elm_Widget_Item *)it, label);         \
+   if (!elm_widget_type_check((it->base.widget), (widtype))) goto label;
+
+
+/**
+ * The drag and drop API.
+ * Currently experimental, and will change when it does dynamic type
+ * addition RSN.
+ *
+ * Here so applications can start to use it, if they ask elm nicely.
+ *
+ * And yes, elm_widget, should probably be elm_experimental...
+ * Complaints about this code should go to /dev/null, or failing that nash.
+ */
+typedef struct _Elm_Selection_Data Elm_Selection_Data;
+
+typedef Eina_Bool (*Elm_Drop_Cb) (void *d, Evas_Object *o, Elm_Selection_Data *data);
+
+typedef enum _Elm_Sel_Type
+{
+   ELM_SEL_PRIMARY,
+   ELM_SEL_SECONDARY,
+   ELM_SEL_CLIPBOARD,
+   ELM_SEL_XDND,
+
+   ELM_SEL_MAX,
+} Elm_Sel_Type;
+
+typedef enum _Elm_Sel_Format
+{
+   /** Plain unformated text: Used for things that don't want rich markup */
+   ELM_SEL_FORMAT_TEXT   = 0x01,
+   /** Edje textblock markup, including inline images */
+   ELM_SEL_FORMAT_MARKUP = 0x02,
+   /** Images */
+   ELM_SEL_FORMAT_IMAGE         = 0x04,
+   /** Vcards */
+   ELM_SEL_FORMAT_VCARD =  0x08,
+   /** Raw HTMLish things for widgets that want that stuff (hello webkit!) */
+   ELM_SEL_FORMAT_HTML = 0x10,
+} Elm_Sel_Format;
+
+struct _Elm_Selection_Data
+{
+   int                   x, y;
+   Elm_Sel_Format        format;
+   void                 *data;
+   int                   len;
+};
+
+Eina_Bool            elm_selection_set(Elm_Sel_Type selection, Evas_Object *widget, Elm_Sel_Format format, const char *buf);
+Eina_Bool            elm_selection_clear(Elm_Sel_Type selection, Evas_Object *widget);
+Eina_Bool            elm_selection_get(Elm_Sel_Type selection, Elm_Sel_Format format, Evas_Object *widget, Elm_Drop_Cb datacb, void *udata);
+Eina_Bool            elm_drop_target_add(Evas_Object *widget, Elm_Sel_Type, Elm_Drop_Cb, void *);
+Eina_Bool            elm_drop_target_del(Evas_Object *widget);
+Eina_Bool            elm_drag_start(Evas_Object *, Elm_Sel_Format, const char *, void (*)(void *,Evas_Object*),void*);
+
+
+#endif
diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c
new file mode 100644 (file)
index 0000000..9241bce
--- /dev/null
@@ -0,0 +1,2505 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Win Win
+ *
+ * The window class of Elementary.  Contains functions to manipulate
+ * windows.
+ */
+
+typedef struct _Elm_Win Elm_Win;
+
+struct _Elm_Win
+{
+   Ecore_Evas *ee;
+   Evas *evas;
+   Evas_Object *parent, *win_obj;
+   Eina_List *subobjs;
+#ifdef HAVE_ELEMENTARY_X
+   Ecore_X_Window xwin;
+   Ecore_Event_Handler *client_message_handler;
+#endif
+   Ecore_Job *deferred_resize_job;
+   Ecore_Job *deferred_child_eval_job;
+
+   Elm_Win_Type type;
+   Elm_Win_Keyboard_Mode kbdmode;
+   Eina_Bool autodel : 1;
+   int *autodel_clear, rot;
+   struct {
+      int x, y;
+   } screen;
+
+   struct {
+      Evas_Object *top;
+
+      struct {
+         Evas_Object *target;
+         Eina_Bool visible : 1;
+         Eina_Bool handled : 1;
+      } cur, prev;
+
+      const char *style;
+      Ecore_Job *reconf_job;
+
+      Eina_Bool enabled : 1;
+      Eina_Bool changed_theme : 1;
+      Eina_Bool top_animate : 1;
+      Eina_Bool geometry_changed : 1;
+   } focus_highlight;
+};
+
+static const char *widtype = NULL;
+static void _elm_win_obj_callback_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _elm_win_obj_callback_parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _elm_win_obj_intercept_show(void *data, Evas_Object *obj);
+static void _elm_win_move(Ecore_Evas *ee);
+static void _elm_win_resize(Ecore_Evas *ee);
+static void _elm_win_delete_request(Ecore_Evas *ee);
+static void _elm_win_resize_job(void *data);
+#ifdef HAVE_ELEMENTARY_X
+static void _elm_win_xwin_update(Elm_Win *win);
+#endif
+static void _elm_win_eval_subobjs(Evas_Object *obj);
+static void _elm_win_subobj_callback_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _elm_win_subobj_callback_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _elm_win_focus_highlight_init(Elm_Win *win);
+static void _elm_win_focus_highlight_shutdown(Elm_Win *win);
+static void _elm_win_focus_highlight_visible_set(Elm_Win *win, Eina_Bool visible);
+static void _elm_win_focus_highlight_reconfigure_job_start(Elm_Win *win);
+static void _elm_win_focus_highlight_reconfigure_job_stop(Elm_Win *win);
+static void _elm_win_focus_highlight_anim_end(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _elm_win_focus_highlight_reconfigure(Elm_Win *win);
+
+Eina_List *_elm_win_list = NULL;
+
+static void
+_elm_win_move(Ecore_Evas *ee)
+{
+   Evas_Object *obj = ecore_evas_object_associate_get(ee);
+   Elm_Win *win;
+   int x, y;
+
+   if (!obj) return;
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
+   win->screen.x = x;
+   win->screen.y = y;
+   evas_object_smart_callback_call(win->win_obj, "moved", NULL);
+}
+
+static void
+_elm_win_resize(Ecore_Evas *ee)
+{
+   Evas_Object *obj = ecore_evas_object_associate_get(ee);
+   Elm_Win *win;
+
+   if (!obj) return;
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   if (win->deferred_resize_job) ecore_job_del(win->deferred_resize_job);
+   win->deferred_resize_job = ecore_job_add(_elm_win_resize_job, win);
+}
+
+static void
+_elm_win_focus_in(Ecore_Evas *ee)
+{
+   Evas_Object *obj = ecore_evas_object_associate_get(ee);
+   Elm_Win *win;
+
+   if (!obj) return;
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   /*NB: Why two different "focus signals" here ??? */
+   evas_object_smart_callback_call(win->win_obj, "focus-in", NULL); // FIXME: remove me
+   evas_object_smart_callback_call(win->win_obj, "focus,in", NULL);
+   win->focus_highlight.cur.visible = EINA_TRUE;
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static void
+_elm_win_focus_out(Ecore_Evas *ee)
+{
+   Evas_Object *obj = ecore_evas_object_associate_get(ee);
+   Elm_Win *win;
+
+   if (!obj) return;
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   evas_object_smart_callback_call(win->win_obj, "focus-out", NULL); // FIXME: remove me
+   evas_object_smart_callback_call(win->win_obj, "focus,out", NULL);
+   win->focus_highlight.cur.visible = EINA_FALSE;
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static Eina_Bool
+_elm_win_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Elm_Win *wd = elm_widget_data_get(obj);
+   const Eina_List *items;
+   void *(*list_data_get) (const Eina_List *list);
+
+   if (!wd)
+     return EINA_FALSE;
+
+   /* Focus chain */
+   if (wd->subobjs)
+     {
+        if (!(items = elm_widget_focus_custom_chain_get(obj)))
+          {
+             items = wd->subobjs;
+             if (!items)
+               return EINA_FALSE;
+          }
+        list_data_get = eina_list_data_get;
+
+        elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
+
+        if (*next)
+          return EINA_TRUE;
+     }
+
+   *next = (Evas_Object *)obj;
+   return EINA_FALSE;
+}
+
+static void
+_elm_win_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
+{
+   if (elm_widget_focus_get(obj))
+     evas_object_focus_set(obj, EINA_TRUE);
+   else
+     evas_object_focus_set(obj, EINA_FALSE);
+}
+
+static Eina_Bool
+_elm_win_event_cb(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
+{
+   if (type == EVAS_CALLBACK_KEY_DOWN)
+     {
+        Evas_Event_Key_Down *ev = event_info;
+        if (!strcmp(ev->keyname, "Tab"))
+          {
+             if(evas_key_modifier_is_set(ev->modifiers, "Shift"))
+               elm_widget_focus_cycle(obj, ELM_FOCUS_PREVIOUS);
+             else
+               elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_deferred_ecore_evas_free(void *data)
+{
+   ecore_evas_free(data);
+}
+
+static void
+_elm_win_obj_callback_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   elm_object_focus(obj);
+}
+
+static void
+_elm_win_obj_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Win *win = data;
+   Evas_Object *child;
+
+   if (win->parent)
+     {
+        evas_object_event_callback_del_full(win->parent, EVAS_CALLBACK_DEL,
+                                            _elm_win_obj_callback_parent_del, win);
+        win->parent = NULL;
+     }
+   if (win->autodel_clear) *(win->autodel_clear) = -1;
+   _elm_win_list = eina_list_remove(_elm_win_list, win->win_obj);
+   while (win->subobjs) elm_win_resize_object_del(obj, win->subobjs->data);
+   ecore_evas_callback_delete_request_set(win->ee, NULL);
+   ecore_evas_callback_resize_set(win->ee, NULL);
+   if (win->deferred_resize_job) ecore_job_del(win->deferred_resize_job);
+   if (win->deferred_child_eval_job) ecore_job_del(win->deferred_child_eval_job);
+   while (((child = evas_object_bottom_get(win->evas))) &&
+         (child != obj))
+     {
+       evas_object_del(child);
+     }
+   while (((child = evas_object_top_get(win->evas))) &&
+         (child != obj))
+     {
+       evas_object_del(child);
+     }
+#ifdef HAVE_ELEMENTARY_X
+   if (win->client_message_handler)
+     ecore_event_handler_del(win->client_message_handler);
+#endif
+// FIXME: Why are we flushing edje on every window destroy ??
+//   edje_file_cache_flush();
+//   edje_collection_cache_flush();
+//   evas_image_cache_flush(win->evas);
+//   evas_font_cache_flush(win->evas);
+// FIXME: we are in the del handler for the object and delete the canvas
+// that lives under it from the handler... nasty. deferring doesn't help either
+   ecore_job_add(_deferred_ecore_evas_free, win->ee);
+//   ecore_evas_free(win->ee);
+
+   _elm_win_focus_highlight_shutdown(win);
+   eina_stringshare_del(win->focus_highlight.style);
+
+   free(win);
+
+   if ((!_elm_win_list) &&
+       (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_CLOSED))
+     {
+        edje_file_cache_flush();
+        edje_collection_cache_flush();
+        evas_image_cache_flush(e);
+        evas_font_cache_flush(e);
+       elm_exit();
+     }
+}
+
+static void
+_elm_win_obj_callback_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Win *win = data;
+   if (obj == win->parent) win->parent = NULL;
+}
+
+static void
+_elm_win_obj_intercept_show(void *data __UNUSED__, Evas_Object *obj)
+{
+   // this is called to make sure all smart containers have calculated their
+   // sizes BEFORE we show the window to make sure it initially appears at
+   // our desired size (ie min size is known first)
+   evas_smart_objects_calculate(evas_object_evas_get(obj));
+   evas_object_show(obj);
+}
+
+static void
+_elm_win_delete_request(Ecore_Evas *ee)
+{
+   Evas_Object *obj = ecore_evas_object_associate_get(ee);
+   Elm_Win *win;
+   if (strcmp(elm_widget_type_get(obj), "win")) return;
+
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   int autodel = win->autodel;
+   win->autodel_clear = &autodel;
+   evas_object_smart_callback_call(win->win_obj, "delete-request", NULL); // FIXME: remove me
+   evas_object_smart_callback_call(win->win_obj, "delete,request", NULL);
+   // FIXME: if above callback deletes - then the below will be invalid
+   if (autodel) evas_object_del(win->win_obj);
+   else win->autodel_clear = NULL;
+}
+
+static void
+_elm_win_resize_job(void *data)
+{
+   Elm_Win *win = data;
+   const Eina_List *l;
+   Evas_Object *obj;
+   int w, h;
+
+   win->deferred_resize_job = NULL;
+   ecore_evas_geometry_get(win->ee, NULL, NULL, &w, &h);
+   evas_object_resize(win->win_obj, w, h);
+   EINA_LIST_FOREACH(win->subobjs, l, obj)
+     {
+       evas_object_move(obj, 0, 0);
+       evas_object_resize(obj, w, h);
+     }
+}
+
+#ifdef HAVE_ELEMENTARY_X
+static void
+_elm_win_xwindow_get(Elm_Win *win)
+{
+   win->xwin = 0;
+
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+   if (ENGINE_COMPARE(ELM_SOFTWARE_X11))
+     {
+       if (win->ee) win->xwin = ecore_evas_software_x11_window_get(win->ee);
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_SDL) ||
+            ENGINE_COMPARE(ELM_SOFTWARE_16_SDL) ||
+            ENGINE_COMPARE(ELM_OPENGL_SDL))
+     {
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_16_X11))
+     {
+       if (win->ee) win->xwin = ecore_evas_software_x11_16_window_get(win->ee);
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_8_X11))
+     {
+       if (win->ee) win->xwin = ecore_evas_software_x11_8_window_get(win->ee);
+     }
+   else if (ENGINE_COMPARE(ELM_XRENDER_X11))
+     {
+       if (win->ee) win->xwin = ecore_evas_xrender_x11_window_get(win->ee);
+     }
+   else if (ENGINE_COMPARE(ELM_OPENGL_X11))
+     {
+       if (win->ee) win->xwin = ecore_evas_gl_x11_window_get(win->ee);
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_WIN32))
+     {
+       if (win->ee) win->xwin = (long)ecore_evas_win32_window_get(win->ee);
+     }
+#undef ENGINE_COMPARE
+}
+#endif
+
+#ifdef HAVE_ELEMENTARY_X
+static void
+_elm_win_xwin_update(Elm_Win *win)
+{
+   _elm_win_xwindow_get(win);
+   if (win->parent)
+     {
+       Elm_Win *win2;
+
+       win2 = elm_widget_data_get(win->parent);
+       if (win2)
+         {
+            if (win->xwin)
+              ecore_x_icccm_transient_for_set(win->xwin, win2->xwin);
+         }
+     }
+
+   if (!win->xwin) return; /* nothing more to do */
+
+   switch (win->type)
+     {
+      case ELM_WIN_BASIC:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_NORMAL);
+        break;
+      case ELM_WIN_DIALOG_BASIC:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DIALOG);
+        break;
+      case ELM_WIN_DESKTOP:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DESKTOP);
+        break;
+      case ELM_WIN_DOCK:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DOCK);
+        break;
+      case ELM_WIN_TOOLBAR:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_TOOLBAR);
+        break;
+      case ELM_WIN_MENU:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_MENU);
+        break;
+      case ELM_WIN_UTILITY:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_UTILITY);
+        break;
+      case ELM_WIN_SPLASH:
+        ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_SPLASH);
+        break;
+      default:
+        break;
+     }
+   ecore_x_e_virtual_keyboard_state_set
+     (win->xwin, (Ecore_X_Virtual_Keyboard_State)win->kbdmode);
+}
+#endif
+
+static void
+_elm_win_eval_subobjs(Evas_Object *obj)
+{
+   const Eina_List *l;
+   const Evas_Object *child;
+
+   Elm_Win *win = elm_widget_data_get(obj);
+   Evas_Coord w, h, minw = -1, minh = -1, maxw = -1, maxh = -1;
+   int xx = 1, xy = 1;
+   double wx, wy;
+
+   EINA_LIST_FOREACH(win->subobjs, l, child)
+     {
+       evas_object_size_hint_weight_get(child, &wx, &wy);
+       if (wx == 0.0) xx = 0;
+       if (wy == 0.0) xy = 0;
+
+       evas_object_size_hint_min_get(child, &w, &h);
+       if (w < 1) w = -1;
+       if (h < 1) h = -1;
+       if (w > minw) minw = w;
+       if (h > minh) minh = h;
+
+       evas_object_size_hint_max_get(child, &w, &h);
+       if (w < 1) w = -1;
+       if (h < 1) h = -1;
+       if (maxw == -1) maxw = w;
+       else if ((w > 0) && (w < maxw)) maxw = w;
+       if (maxh == -1) maxh = h;
+       else if ((h > 0) && (h < maxh)) maxh = h;
+     }
+   if (!xx) maxw = minw;
+   else maxw = 32767;
+   if (!xy) maxh = minh;
+   else maxh = 32767;
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+   evas_object_geometry_get(obj, 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);
+}
+
+static void
+_elm_win_subobj_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Win *win = elm_widget_data_get(data);
+   win->subobjs = eina_list_remove(win->subobjs, obj);
+   _elm_win_eval_subobjs(win->win_obj);
+}
+
+static void
+_elm_win_subobj_callback_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _elm_win_eval_subobjs(data);
+}
+
+void
+_elm_win_shutdown(void)
+{
+   while (_elm_win_list)
+     evas_object_del(_elm_win_list->data);
+}
+
+void
+_elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme)
+{
+   const Eina_List *l;
+   Evas_Object *obj;
+
+   if (!use_theme)
+     {
+        EINA_LIST_FOREACH(_elm_win_list, l, obj)
+          elm_widget_theme(obj);
+     }
+   else
+     {
+        EINA_LIST_FOREACH(_elm_win_list, l, obj)
+          elm_widget_theme_specific(obj, th, EINA_FALSE);
+     }
+}
+
+#ifdef HAVE_ELEMENTARY_X
+static Eina_Bool
+_elm_win_client_message(void *data, int type __UNUSED__, void *event)
+{
+   Elm_Win *win = data;
+   Ecore_X_Event_Client_Message *e = event;
+
+   if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
+   if (e->message_type == ECORE_X_ATOM_E_COMP_FLUSH)
+     {
+        if ((unsigned)e->data.l[0] == win->xwin)
+          {
+             Evas *evas = evas_object_evas_get(win->win_obj);
+             if (evas)
+               {
+                  edje_file_cache_flush();
+                  edje_collection_cache_flush();
+                  evas_image_cache_flush(evas);
+                  evas_font_cache_flush(evas);
+               }
+          }
+     }
+   else if (e->message_type == ECORE_X_ATOM_E_COMP_DUMP)
+     {
+        if ((unsigned)e->data.l[0] == win->xwin)
+          {
+             Evas *evas = evas_object_evas_get(win->win_obj);
+             if (evas)
+               {
+                  edje_file_cache_flush();
+                  edje_collection_cache_flush();
+                  evas_image_cache_flush(evas);
+                  evas_font_cache_flush(evas);
+                  evas_render_dump(evas);
+               }
+          }
+     }
+   return ECORE_CALLBACK_PASS_ON;
+}
+#endif
+
+static void
+_elm_win_focus_target_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Win *win = data;
+
+   win->focus_highlight.geometry_changed = EINA_TRUE;
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static void
+_elm_win_focus_target_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Win *win = data;
+
+   win->focus_highlight.geometry_changed = EINA_TRUE;
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static void
+_elm_win_focus_target_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Win *win = data;
+
+   win->focus_highlight.cur.target = NULL;
+
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static void
+_elm_win_focus_target_callbacks_add(Elm_Win *win)
+{
+   Evas_Object *obj = win->focus_highlight.cur.target;
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
+                                 _elm_win_focus_target_move, win);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
+                                 _elm_win_focus_target_resize, win);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                 _elm_win_focus_target_del, win);
+}
+
+static void
+_elm_win_focus_target_callbacks_del(Elm_Win *win)
+{
+   Evas_Object *obj = win->focus_highlight.cur.target;
+
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
+                                      _elm_win_focus_target_move, win);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
+                                      _elm_win_focus_target_resize, win);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
+                                      _elm_win_focus_target_del, win);
+}
+
+static Evas_Object *
+_elm_win_focus_target_get(Evas_Object *obj)
+{
+   Evas_Object *o = obj;
+
+   do
+     {
+        if (elm_widget_is(o))
+          {
+             if (!elm_widget_highlight_ignore_get(o))
+               break;
+             o = elm_widget_parent_get(o);
+             if (!o)
+               o = evas_object_smart_parent_get(o);
+          }
+        else
+          {
+             o = elm_widget_parent_widget_get(o);
+             if (!o)
+               o = evas_object_smart_parent_get(o);
+          }
+     }
+   while (o);
+
+   return o;
+}
+
+static void
+_elm_win_object_focus_in(void *data, Evas *e __UNUSED__, void *event_info)
+{
+   Evas_Object *obj = event_info, *target;
+   Elm_Win *win = data;
+
+   if (win->focus_highlight.cur.target == obj)
+     return;
+
+   target = _elm_win_focus_target_get(obj);
+   win->focus_highlight.cur.target = target;
+   if (elm_widget_highlight_in_theme_get(target))
+     win->focus_highlight.cur.handled = EINA_TRUE;
+   else
+     _elm_win_focus_target_callbacks_add(win);
+
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static void
+_elm_win_object_focus_out(void *data, Evas *e __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Win *win = data;
+
+   if (!win->focus_highlight.cur.target)
+     return;
+
+   if (!win->focus_highlight.cur.handled)
+     _elm_win_focus_target_callbacks_del(win);
+   win->focus_highlight.cur.target = NULL;
+   win->focus_highlight.cur.handled = EINA_FALSE;
+
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static void
+_elm_win_focus_highlight_hide(void *data __UNUSED__, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   evas_object_hide(obj);
+}
+
+static void
+_elm_win_focus_highlight_init(Elm_Win *win)
+{
+   evas_event_callback_add(win->evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+                           _elm_win_object_focus_in, win);
+   evas_event_callback_add(win->evas,
+                           EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
+                           _elm_win_object_focus_out, win);
+
+   win->focus_highlight.cur.target = evas_focus_get(win->evas);
+
+   win->focus_highlight.top = edje_object_add(win->evas);
+   win->focus_highlight.changed_theme = EINA_TRUE;
+   edje_object_signal_callback_add(win->focus_highlight.top,
+                                   "elm,action,focus,hide,end", "",
+                                   _elm_win_focus_highlight_hide, NULL);
+   edje_object_signal_callback_add(win->focus_highlight.top,
+                                   "elm,action,focus,anim,end", "",
+                                   _elm_win_focus_highlight_anim_end, win);
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+static void
+_elm_win_focus_highlight_shutdown(Elm_Win *win)
+{
+   _elm_win_focus_highlight_reconfigure_job_stop(win);
+   if (win->focus_highlight.cur.target)
+     {
+        _elm_win_focus_target_callbacks_del(win);
+        win->focus_highlight.cur.target = NULL;
+     }
+   if (win->focus_highlight.top)
+     {
+        evas_object_del(win->focus_highlight.top);
+        win->focus_highlight.top = NULL;
+     }
+
+     evas_event_callback_del_full(win->evas,
+                                  EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+                                  _elm_win_object_focus_in, win);
+     evas_event_callback_del_full(win->evas,
+                                  EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
+                                  _elm_win_object_focus_out, win);
+}
+
+static void
+_elm_win_focus_highlight_visible_set(Elm_Win *win, Eina_Bool visible)
+{
+   Evas_Object *top;
+
+   top = win->focus_highlight.top;
+   if (visible)
+     {
+        if (top)
+          {
+             evas_object_show(top);
+             edje_object_signal_emit(top, "elm,action,focus,show", "elm");
+          }
+     }
+   else
+     {
+        if (top)
+          edje_object_signal_emit(top, "elm,action,focus,hide", "elm");
+     }
+}
+
+static void
+_elm_win_focus_highlight_reconfigure_job(void *data)
+{
+   _elm_win_focus_highlight_reconfigure((Elm_Win *)data);
+}
+
+static void
+_elm_win_focus_highlight_reconfigure_job_start(Elm_Win *win)
+{
+   if (win->focus_highlight.reconf_job)
+     ecore_job_del(win->focus_highlight.reconf_job);
+   win->focus_highlight.reconf_job = ecore_job_add(
+      _elm_win_focus_highlight_reconfigure_job, win);
+}
+
+static void
+_elm_win_focus_highlight_reconfigure_job_stop(Elm_Win *win)
+{
+   if (win->focus_highlight.reconf_job)
+     ecore_job_del(win->focus_highlight.reconf_job);
+   win->focus_highlight.reconf_job = NULL;
+}
+
+static void
+_elm_win_focus_highlight_simple_setup(Elm_Win *win, Evas_Object *obj)
+{
+   Evas_Object *clip, *target = win->focus_highlight.cur.target;
+   Evas_Coord x, y, w, h;
+
+   clip = evas_object_clip_get(target);
+   evas_object_geometry_get(target, &x, &y, &w, &h);
+
+   evas_object_move(obj, x, y);
+   evas_object_resize(obj, w, h);
+   evas_object_clip_set(obj, clip);
+}
+
+static void
+_elm_win_focus_highlight_anim_setup(Elm_Win *win, Evas_Object *obj)
+{
+   Evas_Coord tx, ty, tw, th;
+   Evas_Coord w, h, px, py, pw, ph;
+   Edje_Message_Int_Set *m;
+   Evas_Object *previous = win->focus_highlight.prev.target;
+   Evas_Object *target = win->focus_highlight.cur.target;
+
+   evas_object_geometry_get(win->win_obj, NULL, NULL, &w, &h);
+   evas_object_geometry_get(target, &tx, &ty, &tw, &th);
+   evas_object_geometry_get(previous, &px, &py, &pw, &ph);
+   evas_object_move(obj, 0, 0);
+   evas_object_resize(obj, tw, th);
+   evas_object_clip_unset(obj);
+
+   m = alloca(sizeof(*m) + (sizeof(int) * 8));
+   m->count = 8;
+   m->val[0] = px;
+   m->val[1] = py;
+   m->val[2] = pw;
+   m->val[3] = ph;
+   m->val[4] = tx;
+   m->val[5] = ty;
+   m->val[6] = tw;
+   m->val[7] = th;
+   edje_object_message_send(obj, EDJE_MESSAGE_INT_SET, 1, m);
+}
+
+static void
+_elm_win_focus_highlight_anim_end(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Elm_Win *win = data;
+   _elm_win_focus_highlight_simple_setup(win, obj);
+}
+
+static void
+_elm_win_focus_highlight_reconfigure(Elm_Win *win)
+{
+   Evas_Object *target = win->focus_highlight.cur.target;
+   Evas_Object *previous = win->focus_highlight.prev.target;
+   Evas_Object *top = win->focus_highlight.top;
+   Eina_Bool visible_changed;
+   Eina_Bool common_visible;
+   const char *sig = NULL;
+
+   _elm_win_focus_highlight_reconfigure_job_stop(win);
+
+   visible_changed = (win->focus_highlight.cur.visible !=
+                      win->focus_highlight.prev.visible);
+
+   if ((target == previous) && (!visible_changed) &&
+       (!win->focus_highlight.geometry_changed))
+     return;
+
+   if ((previous) && (win->focus_highlight.prev.handled))
+     elm_widget_signal_emit(previous, "elm,action,focus_highlight,hide", "elm");
+
+   if (!target)
+     common_visible = EINA_FALSE;
+   else if (win->focus_highlight.cur.handled)
+     {
+        common_visible = EINA_FALSE;
+        if (win->focus_highlight.cur.visible)
+          sig = "elm,action,focus_highlight,show";
+        else
+          sig = "elm,action,focus_highlight,hide";
+     }
+   else
+     common_visible = win->focus_highlight.cur.visible;
+
+   _elm_win_focus_highlight_visible_set(win, common_visible);
+   if (sig)
+     elm_widget_signal_emit(target, sig, "elm");
+
+   if ((!target) || (!common_visible) || (win->focus_highlight.cur.handled))
+     goto the_end;
+
+   if (win->focus_highlight.changed_theme)
+     {
+        const char *str;
+        if (win->focus_highlight.style)
+          str = win->focus_highlight.style;
+        else
+          str = "default";
+        _elm_theme_object_set(win->win_obj, top, "focus_highlight", "top",
+                              str);
+        win->focus_highlight.changed_theme = EINA_FALSE;
+
+        if (_elm_config->focus_highlight_animate)
+          {
+             str = edje_object_data_get(win->focus_highlight.top, "animate");
+             win->focus_highlight.top_animate = ((str) && (!strcmp(str, "on")));
+          }
+     }
+
+   if ((win->focus_highlight.top_animate) && (previous) &&
+       (!win->focus_highlight.prev.handled))
+     _elm_win_focus_highlight_anim_setup(win, top);
+   else
+     _elm_win_focus_highlight_simple_setup(win, top);
+   evas_object_raise(top);
+
+the_end:
+   win->focus_highlight.geometry_changed = EINA_FALSE;
+   win->focus_highlight.prev = win->focus_highlight.cur;
+}
+
+#ifdef ELM_DEBUG
+static void
+_debug_key_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Key_Down *ev = event_info;
+
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+      return;
+
+
+   if ((strcmp(ev->keyname, "F12")) ||
+       (!evas_key_modifier_is_set(ev->modifiers, "Control")))
+     return;
+
+   printf("Tree graph generated.\n");
+   elm_object_tree_dot_dump(obj, "./dump.dot");
+}
+#endif
+
+/**
+ * Adds a window object. If this is the first window created, pass NULL as
+ * @p parent.
+ *
+ * @param parent Parent object to add the window to, or NULL
+ * @param name The name of the window
+ * @param type The window type, one of the following:
+ * ELM_WIN_BASIC
+ * ELM_WIN_DIALOG_BASIC
+ * ELM_WIN_DESKTOP
+ * ELM_WIN_DOCK
+ * ELM_WIN_TOOLBAR
+ * ELM_WIN_MENU
+ * ELM_WIN_UTILITY
+ * ELM_WIN_SPLASH
+ *
+ * @return The created object, or NULL on failure
+ *
+ * @ingroup Win
+ */
+EAPI Evas_Object *
+elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type)
+{
+   Elm_Win *win;
+   const Eina_List *l;
+   const char *fontpath;
+
+   win = ELM_NEW(Elm_Win);
+
+#define FALLBACK_TRY(engine)                                            \
+   if (!win->ee)                                                        \
+     do {                                                               \
+       CRITICAL(engine " engine creation failed. Trying software X11."); \
+       win->ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 1, 1);      \
+     } while (0)
+
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+   if (ENGINE_COMPARE(ELM_SOFTWARE_X11))
+     {
+       win->ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 1, 1);
+#ifdef HAVE_ELEMENTARY_X
+        win->client_message_handler = ecore_event_handler_add
+          (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
+#endif
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_FB))
+     {
+       win->ee = ecore_evas_fb_new(NULL, 0, 1, 1);
+        FALLBACK_TRY("Sofware FB");
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_DIRECTFB))
+     {
+        win->ee = ecore_evas_directfb_new(NULL, 1, 0, 0, 1, 1);
+        FALLBACK_TRY("Sofware DirectFB");
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_16_X11))
+     {
+       win->ee = ecore_evas_software_x11_16_new(NULL, 0, 0, 0, 1, 1);
+        FALLBACK_TRY("Sofware-16");
+#ifdef HAVE_ELEMENTARY_X
+        win->client_message_handler = ecore_event_handler_add
+          (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
+#endif
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_8_X11))
+     {
+       win->ee = ecore_evas_software_x11_8_new(NULL, 0, 0, 0, 1, 1);
+        FALLBACK_TRY("Sofware-8");
+#ifdef HAVE_ELEMENTARY_X
+        win->client_message_handler = ecore_event_handler_add
+          (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
+#endif
+     }
+   else if (ENGINE_COMPARE(ELM_XRENDER_X11))
+     {
+       win->ee = ecore_evas_xrender_x11_new(NULL, 0, 0, 0, 1, 1);
+        FALLBACK_TRY("XRender");
+#ifdef HAVE_ELEMENTARY_X
+        win->client_message_handler = ecore_event_handler_add
+          (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
+#endif
+     }
+   else if (ENGINE_COMPARE(ELM_OPENGL_X11))
+     {
+       win->ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, 1, 1);
+        FALLBACK_TRY("OpenGL");
+#ifdef HAVE_ELEMENTARY_X
+        win->client_message_handler = ecore_event_handler_add
+          (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
+#endif
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_WIN32))
+     {
+       win->ee = ecore_evas_software_gdi_new(NULL, 0, 0, 1, 1);
+        FALLBACK_TRY("Sofware Win32");
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
+     {
+       win->ee = ecore_evas_software_wince_gdi_new(NULL, 0, 0, 1, 1);
+        FALLBACK_TRY("Sofware-16-WinCE");
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_SDL))
+     {
+       win->ee = ecore_evas_sdl_new(NULL, 0, 0, 0, 0, 0, 1);
+        FALLBACK_TRY("Sofware SDL");
+     }
+   else if (ENGINE_COMPARE(ELM_SOFTWARE_16_SDL))
+     {
+       win->ee = ecore_evas_sdl16_new(NULL, 0, 0, 0, 0, 0, 1);
+        FALLBACK_TRY("Sofware-16-SDL");
+     }
+   else if (ENGINE_COMPARE(ELM_OPENGL_SDL))
+     {
+       win->ee = ecore_evas_gl_sdl_new(NULL, 1, 1, 0, 0);
+        FALLBACK_TRY("OpenGL SDL");
+     }
+#undef FALLBACK_TRY
+
+   if (!win->ee)
+     {
+       ERR("Cannot create window.");
+       free(win);
+       return NULL;
+     }
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+#endif
+   if ((_elm_config->bgpixmap) && (!_elm_config->compositing))
+     ecore_evas_avoid_damage_set(win->ee, ECORE_EVAS_AVOID_DAMAGE_EXPOSE);
+// bg pixmap done by x - has other issues like can be redrawn by x before it
+// is filled/ready by app
+//     ecore_evas_avoid_damage_set(win->ee, ECORE_EVAS_AVOID_DAMAGE_BUILT_IN);
+
+   win->type = type;
+   win->parent = parent;
+   if (win->parent)
+     evas_object_event_callback_add(win->parent, EVAS_CALLBACK_DEL,
+                                    _elm_win_obj_callback_parent_del, win);
+
+   win->evas = ecore_evas_get(win->ee);
+   win->win_obj = elm_widget_add(win->evas);
+   elm_widget_type_set(win->win_obj, "win");
+   ELM_SET_WIDTYPE(widtype, "win");
+   elm_widget_data_set(win->win_obj, win);
+   elm_widget_event_hook_set(win->win_obj, _elm_win_event_cb);
+   elm_widget_on_focus_hook_set(win->win_obj, _elm_win_on_focus_hook, NULL);
+   elm_widget_can_focus_set(win->win_obj, EINA_TRUE);
+   elm_widget_highlight_ignore_set(win->win_obj, EINA_TRUE);
+   elm_widget_focus_next_hook_set(win->win_obj, _elm_win_focus_next_hook);
+   evas_object_color_set(win->win_obj, 0, 0, 0, 0);
+   evas_object_move(win->win_obj, 0, 0);
+   evas_object_resize(win->win_obj, 1, 1);
+   evas_object_layer_set(win->win_obj, 50);
+   evas_object_pass_events_set(win->win_obj, EINA_TRUE);
+
+   evas_object_intercept_show_callback_add(win->win_obj,
+                                           _elm_win_obj_intercept_show, win);
+   ecore_evas_object_associate(win->ee, win->win_obj,
+                              ECORE_EVAS_OBJECT_ASSOCIATE_BASE |
+                              ECORE_EVAS_OBJECT_ASSOCIATE_STACK |
+                              ECORE_EVAS_OBJECT_ASSOCIATE_LAYER);
+   evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_SHOW,
+                                 _elm_win_obj_callback_show, win);
+   evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_DEL,
+                                 _elm_win_obj_callback_del, win);
+
+   ecore_evas_name_class_set(win->ee, name, _elm_appname);
+   ecore_evas_callback_delete_request_set(win->ee, _elm_win_delete_request);
+   ecore_evas_callback_resize_set(win->ee, _elm_win_resize);
+   ecore_evas_callback_focus_in_set(win->ee, _elm_win_focus_in);
+   ecore_evas_callback_focus_out_set(win->ee, _elm_win_focus_out);
+   ecore_evas_callback_move_set(win->ee, _elm_win_move);
+   evas_image_cache_set(win->evas, (_elm_config->image_cache * 1024));
+   evas_font_cache_set(win->evas, (_elm_config->font_cache * 1024));
+   EINA_LIST_FOREACH(_elm_config->font_dirs, l, fontpath)
+     evas_font_path_append(win->evas, fontpath);
+   if (!_elm_config->font_hinting)
+     evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_NONE);
+   else if (_elm_config->font_hinting == 1)
+     evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_AUTO);
+   else if (_elm_config->font_hinting == 2)
+     evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_BYTECODE);
+
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+
+   _elm_win_list = eina_list_append(_elm_win_list, win->win_obj);
+
+   if (ENGINE_COMPARE(ELM_SOFTWARE_FB))
+     {
+       ecore_evas_fullscreen_set(win->ee, 1);
+     }
+#undef ENGINE_COMPARE
+
+   if (_elm_config->focus_highlight_enable)
+     elm_win_focus_highlight_enabled_set(win->win_obj, EINA_TRUE);
+
+#ifdef ELM_DEBUG
+   Evas_Modifier_Mask mask = evas_key_modifier_mask_get(win->evas, "Control");
+   evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_KEY_DOWN,
+                                  _debug_key_down, win);
+   Eina_Bool ret = evas_object_key_grab(win->win_obj, "F12", mask, 0, EINA_TRUE);
+   printf("Key F12 exclusive for dot tree generation. (%d)\n", ret);
+#endif
+   return win->win_obj;
+}
+
+/**
+ * Add @p subobj as a resize object of window @p obj.
+ *
+ * @param obj The window object
+ * @param subobj The resize object to add
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_resize_object_add(Evas_Object *obj, Evas_Object *subobj)
+{
+   Evas_Coord w, h;
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   win->subobjs = eina_list_append(win->subobjs, subobj);
+   elm_widget_sub_object_add(obj, subobj);
+   evas_object_event_callback_add(subobj, EVAS_CALLBACK_DEL,
+                                  _elm_win_subobj_callback_del, obj);
+   evas_object_event_callback_add(subobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                  _elm_win_subobj_callback_changed_size_hints,
+                                  obj);
+   ecore_evas_geometry_get(win->ee, NULL, NULL, &w, &h);
+   evas_object_move(subobj, 0, 0);
+   evas_object_resize(subobj, w, h);
+   _elm_win_eval_subobjs(obj);
+}
+
+/**
+ * Delete @p subobj as a resize object of window @p obj.
+ *
+ * @param obj The window object
+ * @param subobj The resize object to add
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_resize_object_del(Evas_Object *obj, Evas_Object *subobj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   evas_object_event_callback_del_full(subobj,
+                                       EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                       _elm_win_subobj_callback_changed_size_hints,
+                                       obj);
+   evas_object_event_callback_del_full(subobj, EVAS_CALLBACK_DEL,
+                                       _elm_win_subobj_callback_del, obj);
+   win->subobjs = eina_list_remove(win->subobjs, subobj);
+   elm_widget_sub_object_del(obj, subobj);
+   _elm_win_eval_subobjs(obj);
+}
+
+/**
+ * Set the title of the window
+ *
+ * @param obj The window object
+ * @param title The title to set
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_title_set(Evas_Object *obj, const char *title)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_title_set(win->ee, title);
+}
+
+/**
+ * Get the title of the window
+ *
+ * @param obj The window object
+ * @return The title
+ *
+ * @ingroup Win
+ */
+EAPI const char *
+elm_win_title_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   win = elm_widget_data_get(obj);
+   if (!win) return NULL;
+   return ecore_evas_title_get(win->ee);
+}
+
+/**
+ * Set the window's autodel state.
+ *
+ * @param obj The window object
+ * @param autodel If true, the window will automatically delete itself when closed
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_autodel_set(Evas_Object *obj, Eina_Bool autodel)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   win->autodel = autodel;
+}
+
+/**
+ * Get the window's autodel state.
+ *
+ * @param obj The window object
+ * @return If the window will automatically delete itself when closed
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_autodel_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return win->autodel;
+}
+
+/**
+ * Activate a window object.
+ *
+ * @param obj The window object
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_activate(Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_activate(win->ee);
+}
+
+/**
+ * Lower a window object.
+ *
+ * @param obj The window object
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_lower(Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_lower(win->ee);
+}
+
+/**
+ * Raise a window object.
+ *
+ * @param obj The window object
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_raise(Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_raise(win->ee);
+}
+
+/**
+ * Set the borderless state of a window.
+ *
+ * @param obj The window object
+ * @param borderless If true, the window is borderless
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_borderless_set(Evas_Object *obj, Eina_Bool borderless)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_borderless_set(win->ee, borderless);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the borderless state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window is borderless
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_borderless_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return ecore_evas_borderless_get(win->ee);
+}
+
+/**
+ * Set the shaped state of a window.
+ *
+ * @param obj The window object
+ * @param shaped If true, the window is shaped
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_shaped_set(Evas_Object *obj, Eina_Bool shaped)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_shaped_set(win->ee, shaped);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the shaped state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window is shaped
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_shaped_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return ecore_evas_shaped_get(win->ee);
+}
+
+/**
+ * Set the alpha channel state of a window.
+ *
+ * @param obj The window object
+ * @param alpha If true, the window has an alpha channel
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_alpha_set(Evas_Object *obj, Eina_Bool alpha)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+#ifdef HAVE_ELEMENTARY_X
+   if (win->xwin)
+     {
+       if (alpha)
+         {
+            if (!_elm_config->compositing)
+              elm_win_shaped_set(obj, alpha);
+            else
+              ecore_evas_alpha_set(win->ee, alpha);
+         }
+       else
+         ecore_evas_alpha_set(win->ee, alpha);
+       _elm_win_xwin_update(win);
+     }
+   else
+#endif
+     ecore_evas_alpha_set(win->ee, alpha);
+}
+
+/**
+ * Get the alpha channel state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window has an alpha channel
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_alpha_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return ecore_evas_alpha_get(win->ee);
+}
+
+/**
+ * Set the transparency state of a window.
+ *
+ * @param obj The window object
+ * @param transparent If true, the window is transparent
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_transparent_set(Evas_Object *obj, Eina_Bool transparent)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+
+#ifdef HAVE_ELEMENTARY_X
+   if (win->xwin)
+     {
+       ecore_evas_transparent_set(win->ee, transparent);
+       _elm_win_xwin_update(win);
+     }
+   else
+#endif
+     ecore_evas_transparent_set(win->ee, transparent);
+}
+
+/**
+ * Get the transparency state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window is transparent
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_transparent_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+
+   return ecore_evas_transparent_get(win->ee);
+}
+
+/**
+ * Set the override state of a window.
+ *
+ * @param obj The window object
+ * @param override If true, the window is overridden
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_override_set(Evas_Object *obj, Eina_Bool override)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_override_set(win->ee, override);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the override state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window is overridden
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_override_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return ecore_evas_override_get(win->ee);
+}
+
+/**
+ * Set the fullscreen state of a window.
+ *
+ * @param obj The window object
+ * @param fullscreen If true, the window is fullscreen
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_fullscreen_set(Evas_Object *obj, Eina_Bool fullscreen)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+   if (ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
+       ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
+     {
+       // these engines... can ONLY be fullscreen
+       return;
+     }
+   else
+     {
+       ecore_evas_fullscreen_set(win->ee, fullscreen);
+#ifdef HAVE_ELEMENTARY_X
+       _elm_win_xwin_update(win);
+#endif
+     }
+#undef ENGINE_COMPARE
+}
+
+/**
+ * Get the fullscreen state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window is fullscreen
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_fullscreen_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+
+#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
+   if (ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
+       ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
+     {
+       // these engines... can ONLY be fullscreen
+       return EINA_TRUE;
+     }
+   else
+     {
+       return ecore_evas_fullscreen_get(win->ee);
+     }
+#undef ENGINE_COMPARE
+}
+
+/**
+ * Set the maximized state of a window.
+ *
+ * @param obj The window object
+ * @param maximized If true, the window is maximized
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_maximized_set(Evas_Object *obj, Eina_Bool maximized)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_maximized_set(win->ee, maximized);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the maximized state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window is maximized
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_maximized_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return ecore_evas_maximized_get(win->ee);
+}
+
+/**
+ * Set the iconified state of a window.
+ *
+ * @param obj The window object
+ * @param iconified If true, the window is iconified
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_iconified_set(Evas_Object *obj, Eina_Bool iconified)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_iconified_set(win->ee, iconified);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the iconified state of a window.
+ *
+ * @param obj The window object
+ * @return If true, the window is iconified
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_iconified_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return ecore_evas_iconified_get(win->ee);
+}
+
+/**
+ * Set the layer of the window.
+ *
+ * @param obj The window object
+ * @param layer The layer of the window
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_layer_set(Evas_Object *obj, int layer)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_layer_set(win->ee, layer);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the layer of the window.
+ *
+ * @param obj The window object
+ * @return The layer of the window
+ *
+ * @ingroup Win
+ */
+EAPI int
+elm_win_layer_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) -1;
+   win = elm_widget_data_get(obj);
+   if (!win) return -1;
+   return ecore_evas_layer_get(win->ee);
+}
+
+/**
+ * Set the rotation of the window.
+ *
+ * @param obj The window object
+ * @param rotation The rotation of the window, in degrees (0-360)
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_rotation_set(Evas_Object *obj, int rotation)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   if (win->rot == rotation) return;
+   win->rot = rotation;
+   ecore_evas_rotation_set(win->ee, rotation);
+   evas_object_size_hint_min_set(obj, -1, -1);
+   evas_object_size_hint_max_set(obj, -1, -1);
+   _elm_win_eval_subobjs(obj);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Rotates the window and resizes it
+ *
+ * @param obj The window object
+ * @param layer The rotation of the window in degrees (0-360)
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_rotation_with_resize_set(Evas_Object *obj, int rotation)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   if (win->rot == rotation) return;
+   win->rot = rotation;
+   ecore_evas_rotation_with_resize_set(win->ee, rotation);
+   evas_object_size_hint_min_set(obj, -1, -1);
+   evas_object_size_hint_max_set(obj, -1, -1);
+   _elm_win_eval_subobjs(obj);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the rotation of the window.
+ *
+ * @param obj The window object
+ * @return The rotation of the window in degrees (0-360)
+ *
+ * @ingroup Win
+ */
+EAPI int
+elm_win_rotation_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) -1;
+   win = elm_widget_data_get(obj);
+   if (!win) return -1;
+   return win->rot;
+}
+
+/**
+ * Set the sticky state of the window.
+ *
+ * @param obj The window object
+ * @param sticky If true, the window's sticky state is enabled
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_sticky_set(Evas_Object *obj, Eina_Bool sticky)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   ecore_evas_sticky_set(win->ee, sticky);
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwin_update(win);
+#endif
+}
+
+/**
+ * Get the sticky state of the window.
+ *
+ * @param obj The window object
+ * @return If true, the window's sticky state is enabled
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_sticky_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+   return ecore_evas_sticky_get(win->ee);
+}
+
+/**
+ * Sets the keyboard mode of the window.
+ *
+ * @param obj The window object
+ * @param mode The mode to set; one of:
+ * ELM_WIN_KEYBOARD_UNKNOWN
+ * ELM_WIN_KEYBOARD_OFF
+ * ELM_WIN_KEYBOARD_ON
+ * ELM_WIN_KEYBOARD_ALPHA
+ * ELM_WIN_KEYBOARD_NUMERIC
+ * ELM_WIN_KEYBOARD_PIN
+ * ELM_WIN_KEYBOARD_PHONE_NUMBER
+ * ELM_WIN_KEYBOARD_HEX
+ * ELM_WIN_KEYBOARD_TERMINAL
+ * ELM_WIN_KEYBOARD_PASSWORD
+ * ELM_WIN_KEYBOARD_IP
+ * ELM_WIN_KEYBOARD_HOST
+ * ELM_WIN_KEYBOARD_FILE
+ * ELM_WIN_KEYBOARD_URL
+ * ELM_WIN_KEYBOARD_KEYPAD
+ * ELM_WIN_KEYBOARD_J2ME
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_keyboard_mode_set(Evas_Object *obj, Elm_Win_Keyboard_Mode mode)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   if (mode == win->kbdmode) return;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+#endif
+   win->kbdmode = mode;
+#ifdef HAVE_ELEMENTARY_X
+   if (win->xwin)
+     ecore_x_e_virtual_keyboard_state_set
+     (win->xwin, (Ecore_X_Virtual_Keyboard_State)win->kbdmode);
+#endif
+}
+
+/**
+ * Gets the keyboard mode of the window.
+ *
+ * @param obj The window object
+ * @return The mode; one of:
+ * ELM_WIN_KEYBOARD_UNKNOWN
+ * ELM_WIN_KEYBOARD_OFF
+ * ELM_WIN_KEYBOARD_ON
+ * ELM_WIN_KEYBOARD_ALPHA
+ * ELM_WIN_KEYBOARD_NUMERIC
+ * ELM_WIN_KEYBOARD_PIN
+ * ELM_WIN_KEYBOARD_PHONE_NUMBER
+ * ELM_WIN_KEYBOARD_HEX
+ * ELM_WIN_KEYBOARD_TERMINAL
+ * ELM_WIN_KEYBOARD_PASSWORD
+ * ELM_WIN_KEYBOARD_IP
+ * ELM_WIN_KEYBOARD_HOST
+ * ELM_WIN_KEYBOARD_FILE
+ * ELM_WIN_KEYBOARD_URL
+ * ELM_WIN_KEYBOARD_KEYPAD
+ * ELM_WIN_KEYBOARD_J2ME
+ *
+ * @ingroup Win
+ */
+EAPI Elm_Win_Keyboard_Mode
+elm_win_keyboard_mode_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_WIN_KEYBOARD_UNKNOWN;
+   win = elm_widget_data_get(obj);
+   if (!win) return ELM_WIN_KEYBOARD_UNKNOWN;
+   return win->kbdmode;
+}
+
+/**
+ * Sets whether the window is a keyboard.
+ *
+ * @param obj The window object
+ * @param is_keyboard If true, the window is a virtual keyboard
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_keyboard_win_set(Evas_Object *obj, Eina_Bool is_keyboard)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     ecore_x_e_virtual_keyboard_set(win->xwin, is_keyboard);
+#endif
+}
+
+/**
+ * Gets whether the window is a keyboard.
+ *
+ * @param obj The window object
+ * @return If the window is a virtual keyboard
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_keyboard_win_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     return ecore_x_e_virtual_keyboard_get(win->xwin);
+#endif
+   return EINA_FALSE;
+}
+
+/**
+ * Get the screen position of a window.
+ *
+ * @param obj The window object
+ * @param x The int to store the x coordinate to
+ * @param y The int to store the y coordinate to
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_screen_position_get(const Evas_Object *obj, int *x, int *y)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+   if (x) *x = win->screen.x;
+   if (y) *y = win->screen.y;
+}
+
+/**
+ * Set if this window is an illume conformant window
+ *
+ * @param obj The window object
+ * @param conformant The conformant flag (1 = conformant, 0 = non-conformant)
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_conformant_set(Evas_Object *obj, Eina_Bool conformant)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     ecore_x_e_illume_conformant_set(win->xwin, conformant);
+#endif
+}
+
+/**
+ * Get if this window is an illume conformant window
+ *
+ * @param obj The window object
+ * @return A boolean if this window is illume conformant or not
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_conformant_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     return ecore_x_e_illume_conformant_get(win->xwin);
+#endif
+   return EINA_FALSE;
+}
+
+/**
+ * Set a window to be an illume quickpanel window
+ *
+ * By default window objects are not quickpanel windows.
+ *
+ * @param obj The window object
+ * @param quickpanel The quickpanel flag (1 = quickpanel, 0 = normal window)
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_quickpanel_set(Evas_Object *obj, Eina_Bool quickpanel)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     {
+        ecore_x_e_illume_quickpanel_set(win->xwin, quickpanel);
+        if (quickpanel)
+          {
+             Ecore_X_Window_State states[2];
+
+             states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
+             states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
+             ecore_x_netwm_window_state_set(win->xwin, states, 2);
+             ecore_x_icccm_hints_set(win->xwin, 0, 0, 0, 0, 0, 0, 0);
+          }
+     }
+#endif
+}
+
+/**
+ * Get if this window is a quickpanel or not
+ *
+ * @param obj The window object
+ * @return A boolean if this window is a quickpanel or not
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_quickpanel_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   win = elm_widget_data_get(obj);
+   if (!win) return EINA_FALSE;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     return ecore_x_e_illume_quickpanel_get(win->xwin);
+#endif
+   return EINA_FALSE;
+}
+
+/**
+ * Set the major priority of a quickpanel window
+ *
+ * @param obj The window object
+ * @param priority The major priority for this quickpanel
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_quickpanel_priority_major_set(Evas_Object *obj, int priority)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     ecore_x_e_illume_quickpanel_priority_major_set(win->xwin, priority);
+#endif
+}
+
+/**
+ * Get the major priority of a quickpanel window
+ *
+ * @param obj The window object
+ * @return The major priority of this quickpanel
+ *
+ * @ingroup Win
+ */
+EAPI int
+elm_win_quickpanel_priority_major_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) -1;
+   win = elm_widget_data_get(obj);
+   if (!win) return -1;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     return ecore_x_e_illume_quickpanel_priority_major_get(win->xwin);
+#endif
+   return -1;
+}
+
+/**
+ * Set the minor priority of a quickpanel window
+ *
+ * @param obj The window object
+ * @param priority The minor priority for this quickpanel
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_quickpanel_priority_minor_set(Evas_Object *obj, int priority)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     ecore_x_e_illume_quickpanel_priority_minor_set(win->xwin, priority);
+#endif
+}
+
+/**
+ * Get the minor priority of a quickpanel window
+ *
+ * @param obj The window object
+ * @return The minor priority of this quickpanel
+ *
+ * @ingroup Win
+ */
+EAPI int
+elm_win_quickpanel_priority_minor_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) -1;
+   win = elm_widget_data_get(obj);
+   if (!win) return -1;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     return ecore_x_e_illume_quickpanel_priority_minor_get(win->xwin);
+#endif
+   return -1;
+}
+
+/**
+ * Set which zone this quickpanel should appear in
+ *
+ * @param obj The window object
+ * @param zone The requested zone for this quickpanel
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_quickpanel_zone_set(Evas_Object *obj, int zone)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   win = elm_widget_data_get(obj);
+   if (!win) return;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     ecore_x_e_illume_quickpanel_zone_set(win->xwin, zone);
+#endif
+}
+
+/**
+ * Get which zone this quickpanel should appear in
+ *
+ * @param obj The window object
+ * @return The requested zone for this quickpanel
+ *
+ * @ingroup Win
+ */
+EAPI int
+elm_win_quickpanel_zone_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+   ELM_CHECK_WIDTYPE(obj, widtype) 0;
+   win = elm_widget_data_get(obj);
+   if (!win) return 0;
+#ifdef HAVE_ELEMENTARY_X
+   _elm_win_xwindow_get(win);
+   if (win->xwin)
+     return ecore_x_e_illume_quickpanel_zone_get(win->xwin);
+#endif
+   return 0;
+}
+
+/**
+ * Set the enabled status for the focus highlight in a window
+ *
+ * This function will enable or disable the focus highlight only for the
+ * given window, regardless of the global setting for it
+ *
+ * @param obj The window where to enable the highlight
+ * @param enabled The enabled value for the highlight
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_focus_highlight_enabled_set(Evas_Object *obj, Eina_Bool enabled)
+{
+   Elm_Win *win;
+
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   win = elm_widget_data_get(obj);
+   enabled = !!enabled;
+   if (win->focus_highlight.enabled == enabled)
+     return;
+
+   win->focus_highlight.enabled = enabled;
+
+   if (win->focus_highlight.enabled)
+     _elm_win_focus_highlight_init(win);
+   else
+     _elm_win_focus_highlight_shutdown(win);
+}
+
+/**
+ * Get the enabled value of the focus highlight for this window
+ *
+ * @param obj The window in which to check if the focus highlight is enabled
+ *
+ * @return EINA_TRUE if enabled, EINA_FALSE otherwise
+ *
+ * @ingroup Win
+ */
+EAPI Eina_Bool
+elm_win_focus_highlight_enabled_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+
+   win = elm_widget_data_get(obj);
+   return win->focus_highlight.enabled;
+}
+
+/**
+ * Set the style for the focus highlight on this window
+ *
+ * Sets the style to use for theming the highlight of focused objects on
+ * the given window. If @p style is NULL, the default will be used.
+ *
+ * @param obj The window where to set the style
+ * @param style The style to set
+ *
+ * @ingroup Win
+ */
+EAPI void
+elm_win_focus_highlight_style_set(Evas_Object *obj, const char *style)
+{
+   Elm_Win *win;
+
+   ELM_CHECK_WIDTYPE(obj, widtype);
+
+   win = elm_widget_data_get(obj);
+   eina_stringshare_replace(&win->focus_highlight.style, style);
+   win->focus_highlight.changed_theme = EINA_TRUE;
+   _elm_win_focus_highlight_reconfigure_job_start(win);
+}
+
+/**
+ * Get the style set for the focus highlight object
+ *
+ * Gets the style set for this windows highilght object, or NULL if none
+ * is set.
+ *
+ * @param obj The window to retrieve the highlights style from
+ *
+ * @return The style set or NULL if none was. Default is used in that case.
+ *
+ * @ingroup Win
+ */
+EAPI const char *
+elm_win_focus_highlight_style_get(const Evas_Object *obj)
+{
+   Elm_Win *win;
+
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+
+   win = elm_widget_data_get(obj);
+   return win->focus_highlight.style;
+}
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *frm;
+   Evas_Object *content;
+};
+
+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 const char *widtype2 = NULL;
+
+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);
+   _elm_theme_object_set(obj, wd->frm, "win", "inwin", elm_widget_style_get(obj));
+   if (wd->content)
+     edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content);
+   _sizing_eval(obj);
+}
+
+static Eina_Bool
+_elm_inwin_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd)
+     return EINA_FALSE;
+
+   /* Try Focus cycle in subitem */
+   if (wd->content)
+     {
+        elm_widget_focus_next_get(wd->content, dir, next);
+        if (*next)
+          return EINA_TRUE;
+     }
+
+   *next = (Evas_Object *)obj;
+   return EINA_FALSE;
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1;
+
+   evas_object_size_hint_min_get(wd->content, &minw, &minh);
+   edje_object_size_min_calc(wd->frm, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _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 (sub == wd->content)
+     {
+       evas_object_event_callback_del_full
+          (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+       wd->content = NULL;
+       _sizing_eval(obj);
+     }
+}
+
+/**
+ * @defgroup Inwin Inwin
+ *
+ * An inwin is a window inside a window that is useful for a quick popup.  It does not hover.
+ */
+EAPI Evas_Object *
+elm_win_inwin_add(Evas_Object *obj)
+{
+   Evas_Object *obj2;
+   Widget_Data *wd;
+   Elm_Win *win;
+
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   win = elm_widget_data_get(obj);
+   if (!win) return NULL;
+   wd = ELM_NEW(Widget_Data);
+   obj2 = elm_widget_add(win->evas);
+   elm_widget_type_set(obj2, "inwin");
+   ELM_SET_WIDTYPE(widtype2, "inwin");
+   elm_widget_sub_object_add(obj, obj2);
+   evas_object_size_hint_weight_set(obj2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(obj2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_win_resize_object_add(obj, obj2);
+
+   elm_widget_data_set(obj2, wd);
+   elm_widget_del_hook_set(obj2, _del_hook);
+   elm_widget_theme_hook_set(obj2, _theme_hook);
+   elm_widget_focus_next_hook_set(obj2, _elm_inwin_focus_next_hook);
+   elm_widget_can_focus_set(obj2, EINA_TRUE);
+   elm_widget_highlight_ignore_set(obj2, EINA_TRUE);
+
+   wd->frm = edje_object_add(win->evas);
+   _elm_theme_object_set(obj, wd->frm, "win", "inwin", "default");
+   elm_widget_resize_object_set(obj2, wd->frm);
+
+   evas_object_smart_callback_add(obj2, "sub-object-del", _sub_del, obj2);
+
+   _sizing_eval(obj2);
+   return obj2;
+}
+
+/**
+ * Activates an inwin object
+ *
+ * @param obj The inwin to activate
+ *
+ * @ingroup Inwin
+ */
+EAPI void
+elm_win_inwin_activate(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype2);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_raise(obj);
+   evas_object_show(obj);
+   edje_object_signal_emit(wd->frm, "elm,action,show", "elm");
+   elm_object_focus(obj);
+}
+
+/**
+ * Set the content of an inwin object.
+ *
+ * Once the content object is set, a previously set one will be deleted.
+ * If you want to keep that old content object, use the
+ * elm_win_inwin_content_unset() function.
+ *
+ * @param obj The inwin object
+ * @param content The object to set as content
+ *
+ * @ingroup Inwin
+ */
+EAPI void
+elm_win_inwin_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype2);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->content == content) return;
+   if (wd->content) evas_object_del(wd->content);
+   wd->content = content;
+   if (content)
+     {
+       elm_widget_sub_object_add(obj, content);
+       evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->frm, "elm.swallow.content", content);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the content of an inwin object.
+ *
+ * Return the content object which is set for this widget.
+ *
+ * @param obj The inwin object
+ * @return The content that is being used
+ *
+ * @ingroup Inwin
+ */
+EAPI Evas_Object *
+elm_win_inwin_content_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype2) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return wd->content;
+}
+
+/**
+ * Unset the content of an inwin object.
+ *
+ * Unparent and return the content object which was set for this widget.
+ *
+ * @param obj The inwin object
+ * @return The content that was being used
+ *
+ * @ingroup Inwin
+ */
+EAPI Evas_Object *
+elm_win_inwin_content_unset(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype2) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (!wd->content) return NULL;
+   Evas_Object *content = wd->content;
+   elm_widget_sub_object_del(obj, wd->content);
+   edje_object_part_unswallow(wd->frm, wd->content);
+   wd->content = NULL;
+   return content;
+}
+
+/* windowing spcific calls - shall we do this differently? */
+/**
+ * Get the Ecore_X_Window of an Evas_Object
+ *
+ * @param obj The object
+ *
+ * @return The Ecore_X_Window of @p obj
+ *
+ * @ingroup Win
+ */
+EAPI Ecore_X_Window
+elm_win_xwindow_get(const Evas_Object *obj)
+{
+   Ecore_X_Window xwin = 0;
+   Ecore_Evas *ee = NULL;
+   if (!obj) return 0;
+#ifdef HAVE_ELEMENTARY_X
+   ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+   if (ee) xwin = (Ecore_X_Window)ecore_evas_window_get(ee);
+   return xwin;
+#else
+   return 0;
+#endif
+}
diff --git a/src/lib/els_box.c b/src/lib/els_box.c
new file mode 100644 (file)
index 0000000..46b47aa
--- /dev/null
@@ -0,0 +1,220 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+static void
+_smart_extents_calculate(Evas_Object *box, Evas_Object_Box_Data *priv, int horizontal, int homogeneous)
+{
+   Evas_Coord minw, minh, mnw, mnh;
+   const Eina_List *l;
+   Evas_Object_Box_Option *opt;
+
+   /* FIXME: need to calc max */
+   minw = 0;
+   minh = 0;
+   if (homogeneous)
+     {
+       EINA_LIST_FOREACH(priv->children, l, opt)
+         {
+            evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
+            if (minh < mnh) minh = mnh;
+            if (minw < mnw) minw = mnw;
+         }
+       if (horizontal)
+          minw *= eina_list_count(priv->children);
+       else
+          minh *= eina_list_count(priv->children);
+     }
+   else
+     {
+       EINA_LIST_FOREACH(priv->children, l, opt)
+         {
+            evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
+            if (horizontal)
+              {
+                 if (minh < mnh) minh = mnh;
+                 minw += mnw;
+              }
+            else
+              {
+                 if (minw < mnw) minw = mnw;
+                 minh += mnh;
+              }
+         }
+     }
+   evas_object_size_hint_min_set(box, minw, minh);
+}
+
+void
+_els_box_layout(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous)
+{
+   Evas_Coord x, y, w, h, xx, yy;
+   const Eina_List *l;
+   Evas_Object *obj;
+   Evas_Coord minw, minh, wdif, hdif;
+   int count = 0, expand = 0;
+   double ax, ay;
+   Evas_Object_Box_Option *opt;
+
+   _smart_extents_calculate(o, priv, horizontal, homogeneous);
+
+   evas_object_geometry_get(o, &x, &y, &w, &h);
+
+   evas_object_size_hint_min_get(o, &minw, &minh);
+   evas_object_size_hint_align_get(o, &ax, &ay);
+   count = eina_list_count(priv->children);
+   if (w < minw)
+     {
+       x = x + ((w - minw) * (1.0 - ax));
+       w = minw;
+     }
+   if (h < minh)
+     {
+       y = y + ((h - minh) * (1.0 - ay));
+       h = minh;
+     }
+   EINA_LIST_FOREACH(priv->children, l, opt)
+     {
+        double wx, wy;
+
+       evas_object_size_hint_weight_get(opt->obj, &wx, &wy);
+       if (horizontal)
+         {
+            if (wx > 0.0) expand++;
+         }
+       else
+         {
+            if (wy > 0.0) expand++;
+         }
+     }
+   if (!expand)
+     {
+       evas_object_size_hint_align_get(o, &ax, &ay);
+       if (horizontal)
+         {
+            x += (double)(w - minw) * ax;
+            w = minw;
+         }
+       else
+         {
+            y += (double)(h - minh) * ay;
+            h = minh;
+         }
+     }
+   wdif = w - minw;
+   hdif = h - minh;
+   xx = x;
+   yy = y;
+   EINA_LIST_FOREACH(priv->children, l, opt)
+     {
+        Evas_Coord mnw, mnh, mxw, mxh;
+        double wx, wy;
+        int fw, fh, xw, xh;
+
+       obj = opt->obj;
+       evas_object_size_hint_align_get(obj, &ax, &ay);
+       evas_object_size_hint_weight_get(obj, &wx, &wy);
+       evas_object_size_hint_min_get(obj, &mnw, &mnh);
+       evas_object_size_hint_max_get(obj, &mxw, &mxh);
+       fw = fh = 0;
+       xw = xh = 0;
+       if (ax == -1.0) {fw = 1; ax = 0.5;}
+       if (ay == -1.0) {fh = 1; ay = 0.5;}
+       if (wx > 0.0) xw = 1;
+       if (wy > 0.0) xh = 1;
+       if (horizontal)
+         {
+            if (homogeneous)
+              {
+                 Evas_Coord ww, hh, ow, oh;
+
+                 ww = (w / (Evas_Coord)count);
+                 hh = h;
+                 ow = mnw;
+                 if (fw) ow = ww;
+                 if ((mxw >= 0) && (mxw < ow))
+                   ow = mxw;
+                 oh = mnh;
+                 if (fh) oh = hh;
+                 if ((mxh >= 0) && (mxh < oh))
+                   oh = mxh;
+                 evas_object_move(obj,
+                                  xx + (Evas_Coord)(((double)(ww - ow)) * ax),
+                                  yy + (Evas_Coord)(((double)(hh - oh)) * ay));
+                 evas_object_resize(obj, ow, oh);
+                 xx += ww;
+              }
+            else
+              {
+                 Evas_Coord ww, hh, ow, oh;
+
+                 ww = mnw;
+                 if ((expand > 0) && (xw))
+                   {
+                      if (expand == 1) ow = wdif;
+                      else ow = (w - minw) / expand;
+                      wdif -= ow;
+                      ww += ow;
+                   }
+                 hh = h;
+                 ow = mnw;
+                 if (fw) ow = ww;
+                 if ((mxw >= 0) && (mxw < ow)) ow = mxw;
+                 oh = mnh;
+                 if (fh) oh = hh;
+                 if ((mxh >= 0) && (mxh < oh)) oh = mxh;
+                 evas_object_move(obj,
+                                  xx + (Evas_Coord)(((double)(ww - ow)) * ax),
+                                  yy + (Evas_Coord)(((double)(hh - oh)) * ay));
+                 evas_object_resize(obj, ow, oh);
+                 xx += ww;
+              }
+         }
+       else
+         {
+            if (homogeneous)
+              {
+                 Evas_Coord ww, hh, ow, oh;
+
+                 ww = w;
+                 hh = (h / (Evas_Coord)count);
+                 ow = mnw;
+                 if (fw) ow = ww;
+                 if ((mxw >= 0) && (mxw < ow)) ow = mxw;
+                 oh = mnh;
+                 if (fh) oh = hh;
+                 if ((mxh >= 0) && (mxh < oh)) oh = mxh;
+                 evas_object_move(obj,
+                                  xx + (Evas_Coord)(((double)(ww - ow)) * ax),
+                                  yy + (Evas_Coord)(((double)(hh - oh)) * ay));
+                 evas_object_resize(obj, ow, oh);
+                 yy += hh;
+              }
+            else
+              {
+                 Evas_Coord ww, hh, ow, oh;
+
+                 ww = w;
+                 hh = mnh;
+                 if ((expand > 0) && (xh))
+                   {
+                      if (expand == 1) oh = hdif;
+                      else oh = (h - minh) / expand;
+                      hdif -= oh;
+                      hh += oh;
+                   }
+                 ow = mnw;
+                 if (fw) ow = ww;
+                 if ((mxw >= 0) && (mxw < ow)) ow = mxw;
+                 oh = mnh;
+                 if (fh) oh = hh;
+                 if ((mxh >= 0) && (mxh < oh)) oh = mxh;
+                 evas_object_move(obj,
+                                  xx + (Evas_Coord)(((double)(ww - ow)) * ax),
+                                  yy + (Evas_Coord)(((double)(hh - oh)) * ay));
+                 evas_object_resize(obj, ow, oh);
+                 yy += hh;
+              }
+         }
+     }
+}
+
diff --git a/src/lib/els_box.h b/src/lib/els_box.h
new file mode 100644 (file)
index 0000000..e394884
--- /dev/null
@@ -0,0 +1 @@
+void _els_box_layout(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous);
diff --git a/src/lib/els_cursor.c b/src/lib/els_cursor.c
new file mode 100644 (file)
index 0000000..45b0ed1
--- /dev/null
@@ -0,0 +1,617 @@
+#include <Elementary.h>
+#include <Elementary_Cursor.h>
+#include "elm_priv.h"
+
+#ifdef HAVE_ELEMENTARY_X
+#include <Ecore_X.h>
+#include <Ecore_X_Cursor.h>
+#endif
+
+/**
+ * @defgroup Cursors Cursors
+ *
+ * The Cursor is an internal smart object used to customize the
+ * cursor displayed over objects (or widgets).
+ * It can use default X cursors (if using X), or cursors from a
+ * theme.
+ */
+
+#define _cursor_key "_elm_cursor"
+
+struct _Cursor_Id 
+{
+   const char *name;
+#ifdef HAVE_ELEMENTARY_X
+   int id;
+#endif
+};
+
+#ifdef HAVE_ELEMENTARY_X
+#define CURSOR(_name, _xid) \
+   {_name , _xid}
+# else
+#define CURSOR(_name, _xid) \
+   {_name}
+#endif
+
+/* Please keep order in sync with Ecore_X_Cursor.h values! */
+struct _Cursor_Id _cursors[] =
+{
+   CURSOR(ELM_CURSOR_X                  , ECORE_X_CURSOR_X                  ),
+   CURSOR(ELM_CURSOR_ARROW              , ECORE_X_CURSOR_ARROW              ),
+   CURSOR(ELM_CURSOR_BASED_ARROW_DOWN   , ECORE_X_CURSOR_BASED_ARROW_DOWN   ),
+   CURSOR(ELM_CURSOR_BASED_ARROW_UP     , ECORE_X_CURSOR_UP                 ),
+   CURSOR(ELM_CURSOR_BOAT               , ECORE_X_CURSOR_BOAT               ),
+   CURSOR(ELM_CURSOR_BOGOSITY           , ECORE_X_CURSOR_BOGOSITY           ),
+   CURSOR(ELM_CURSOR_BOTTOM_LEFT_CORNER , ECORE_X_CURSOR_BOTTOM_LEFT_CORNER ),
+   CURSOR(ELM_CURSOR_BOTTOM_RIGHT_CORNER, ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER),
+   CURSOR(ELM_CURSOR_BOTTOM_SIDE        , ECORE_X_CURSOR_BOTTOM_SIDE        ),
+   CURSOR(ELM_CURSOR_BOTTOM_TEE         , ECORE_X_CURSOR_BOTTOM_TEE         ),
+   CURSOR(ELM_CURSOR_BOX_SPIRAL         , ECORE_X_CURSOR_BOX_SPIRAL         ),
+   CURSOR(ELM_CURSOR_CENTER_PTR         , ECORE_X_CURSOR_CENTER_PTR         ),
+   CURSOR(ELM_CURSOR_CIRCLE             , ECORE_X_CURSOR_CIRCLE             ),
+   CURSOR(ELM_CURSOR_CLOCK              , ECORE_X_CURSOR_CLOCK              ),
+   CURSOR(ELM_CURSOR_COFFEE_MUG         , ECORE_X_CURSOR_COFFEE_MUG         ),
+   CURSOR(ELM_CURSOR_CROSS              , ECORE_X_CURSOR_CROSS              ),
+   CURSOR(ELM_CURSOR_CROSS_REVERSE      , ECORE_X_CURSOR_CROSS_REVERSE      ),
+   CURSOR(ELM_CURSOR_CROSSHAIR          , ECORE_X_CURSOR_CROSSHAIR          ),
+   CURSOR(ELM_CURSOR_DIAMOND_CROSS      , ECORE_X_CURSOR_DIAMOND_CROSS      ),
+   CURSOR(ELM_CURSOR_DOT                , ECORE_X_CURSOR_DOT                ),
+   CURSOR(ELM_CURSOR_DOT_BOX_MASK       , ECORE_X_CURSOR_DOT_BOX_MASK       ),
+   CURSOR(ELM_CURSOR_DOUBLE_ARROW       , ECORE_X_CURSOR_DOUBLE_ARROW       ),
+   CURSOR(ELM_CURSOR_DRAFT_LARGE        , ECORE_X_CURSOR_DRAFT_LARGE        ),
+   CURSOR(ELM_CURSOR_DRAFT_SMALL        , ECORE_X_CURSOR_DRAFT_SMALL        ),
+   CURSOR(ELM_CURSOR_DRAPED_BOX         , ECORE_X_CURSOR_DRAPED_BOX         ),
+   CURSOR(ELM_CURSOR_EXCHANGE           , ECORE_X_CURSOR_EXCHANGE           ),
+   CURSOR(ELM_CURSOR_FLEUR              , ECORE_X_CURSOR_FLEUR              ),
+   CURSOR(ELM_CURSOR_GOBBLER            , ECORE_X_CURSOR_GOBBLER            ),
+   CURSOR(ELM_CURSOR_GUMBY              , ECORE_X_CURSOR_GUMBY              ),
+   CURSOR(ELM_CURSOR_HAND1              , ECORE_X_CURSOR_HAND1              ),
+   CURSOR(ELM_CURSOR_HAND2              , ECORE_X_CURSOR_HAND2              ),
+   CURSOR(ELM_CURSOR_HEART              , ECORE_X_CURSOR_HEART              ),
+   CURSOR(ELM_CURSOR_ICON               , ECORE_X_CURSOR_ICON               ),
+   CURSOR(ELM_CURSOR_IRON_CROSS         , ECORE_X_CURSOR_IRON_CROSS         ),
+   CURSOR(ELM_CURSOR_LEFT_PTR           , ECORE_X_CURSOR_LEFT_PTR           ),
+   CURSOR(ELM_CURSOR_LEFT_SIDE          , ECORE_X_CURSOR_LEFT_SIDE          ),
+   CURSOR(ELM_CURSOR_LEFT_TEE           , ECORE_X_CURSOR_LEFT_TEE           ),
+   CURSOR(ELM_CURSOR_LEFTBUTTON         , ECORE_X_CURSOR_LEFTBUTTON         ),
+   CURSOR(ELM_CURSOR_LL_ANGLE           , ECORE_X_CURSOR_LL_ANGLE           ),
+   CURSOR(ELM_CURSOR_LR_ANGLE           , ECORE_X_CURSOR_LR_ANGLE           ),
+   CURSOR(ELM_CURSOR_MAN                , ECORE_X_CURSOR_MAN                ),
+   CURSOR(ELM_CURSOR_MIDDLEBUTTON       , ECORE_X_CURSOR_MIDDLEBUTTON       ),
+   CURSOR(ELM_CURSOR_MOUSE              , ECORE_X_CURSOR_MOUSE              ),
+   CURSOR(ELM_CURSOR_PENCIL             , ECORE_X_CURSOR_PENCIL             ),
+   CURSOR(ELM_CURSOR_PIRATE             , ECORE_X_CURSOR_PIRATE             ),
+   CURSOR(ELM_CURSOR_PLUS               , ECORE_X_CURSOR_PLUS               ),
+   CURSOR(ELM_CURSOR_QUESTION_ARROW     , ECORE_X_CURSOR_QUESTION_ARROW     ),
+   CURSOR(ELM_CURSOR_RIGHT_PTR          , ECORE_X_CURSOR_RIGHT_PTR          ),
+   CURSOR(ELM_CURSOR_RIGHT_SIDE         , ECORE_X_CURSOR_RIGHT_SIDE         ),
+   CURSOR(ELM_CURSOR_RIGHT_TEE          , ECORE_X_CURSOR_RIGHT_TEE          ),
+   CURSOR(ELM_CURSOR_RIGHTBUTTON        , ECORE_X_CURSOR_RIGHTBUTTON        ),
+   CURSOR(ELM_CURSOR_RTL_LOGO           , ECORE_X_CURSOR_RTL_LOGO           ),
+   CURSOR(ELM_CURSOR_SAILBOAT           , ECORE_X_CURSOR_SAILBOAT           ),
+   CURSOR(ELM_CURSOR_SB_DOWN_ARROW      , ECORE_X_CURSOR_SB_DOWN_ARROW      ),
+   CURSOR(ELM_CURSOR_SB_H_DOUBLE_ARROW  , ECORE_X_CURSOR_SB_H_DOUBLE_ARROW  ),
+   CURSOR(ELM_CURSOR_SB_LEFT_ARROW      , ECORE_X_CURSOR_SB_LEFT_ARROW      ),
+   CURSOR(ELM_CURSOR_SB_RIGHT_ARROW     , ECORE_X_CURSOR_SB_RIGHT_ARROW     ),
+   CURSOR(ELM_CURSOR_SB_UP_ARROW        , ECORE_X_CURSOR_SB_UP_ARROW        ),
+   CURSOR(ELM_CURSOR_SB_V_DOUBLE_ARROW  , ECORE_X_CURSOR_SB_V_DOUBLE_ARROW  ),
+   CURSOR(ELM_CURSOR_SHUTTLE            , ECORE_X_CURSOR_SHUTTLE            ),
+   CURSOR(ELM_CURSOR_SIZING             , ECORE_X_CURSOR_SIZING             ),
+   CURSOR(ELM_CURSOR_SPIDER             , ECORE_X_CURSOR_SPIDER             ),
+   CURSOR(ELM_CURSOR_SPRAYCAN           , ECORE_X_CURSOR_SPRAYCAN           ),
+   CURSOR(ELM_CURSOR_STAR               , ECORE_X_CURSOR_STAR               ),
+   CURSOR(ELM_CURSOR_TARGET             , ECORE_X_CURSOR_TARGET             ),
+   CURSOR(ELM_CURSOR_TCROSS             , ECORE_X_CURSOR_TCROSS             ),
+   CURSOR(ELM_CURSOR_TOP_LEFT_ARROW     , ECORE_X_CURSOR_TOP_LEFT_ARROW     ),
+   CURSOR(ELM_CURSOR_TOP_LEFT_CORNER    , ECORE_X_CURSOR_TOP_LEFT_CORNER    ),
+   CURSOR(ELM_CURSOR_TOP_RIGHT_CORNER   , ECORE_X_CURSOR_TOP_RIGHT_CORNER   ),
+   CURSOR(ELM_CURSOR_TOP_SIDE           , ECORE_X_CURSOR_TOP_SIDE           ),
+   CURSOR(ELM_CURSOR_TOP_TEE            , ECORE_X_CURSOR_TOP_TEE            ),
+   CURSOR(ELM_CURSOR_TREK               , ECORE_X_CURSOR_TREK               ),
+   CURSOR(ELM_CURSOR_UL_ANGLE           , ECORE_X_CURSOR_UL_ANGLE           ),
+   CURSOR(ELM_CURSOR_UMBRELLA           , ECORE_X_CURSOR_UMBRELLA           ),
+   CURSOR(ELM_CURSOR_UR_ANGLE           , ECORE_X_CURSOR_UR_ANGLE           ),
+   CURSOR(ELM_CURSOR_WATCH              , ECORE_X_CURSOR_WATCH              ),
+   CURSOR(ELM_CURSOR_XTERM              , ECORE_X_CURSOR_XTERM              )
+};
+static const int _cursors_count = sizeof(_cursors)/sizeof(struct _Cursor_Id);
+
+#define ELM_CURSOR_GET_OR_RETURN(cur, obj, ...)         \
+  Elm_Cursor *cur;                                      \
+  do                                                    \
+    {                                                   \
+       if (!(obj))                                      \
+         {                                              \
+            CRITICAL("Null pointer: " #obj);            \
+            return __VA_ARGS__;                         \
+         }                                              \
+       cur = evas_object_data_get((obj), _cursor_key);  \
+       if (!cur)                                        \
+         {                                              \
+            ERR("Object does not have cursor: " #obj);  \
+            return __VA_ARGS__;                         \
+         }                                              \
+    }                                                   \
+  while (0)
+
+struct _Elm_Cursor
+{
+   Evas_Object *obj;
+   Evas_Object *eventarea, *owner;
+   const char *style, *cursor_name;
+   int hot_x, hot_y;
+   Ecore_Evas *ee;
+   Evas *evas;
+#ifdef HAVE_ELEMENTARY_X
+   Ecore_X_Cursor cursor;
+   Ecore_X_Window win;
+#endif
+   Eina_Bool visible:1;
+   Eina_Bool use_engine:1;
+   Eina_Bool engine_only:1;
+};
+
+static void
+_elm_cursor_obj_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Cursor *cur = data;
+
+   if (cur) cur->obj = NULL;
+}
+
+static Eina_Bool
+_elm_cursor_obj_add(Evas_Object *obj, Elm_Cursor *cur)
+{
+   int x, y;
+
+   cur->obj = edje_object_add(cur->evas);
+
+   if (!cur->obj)
+     return EINA_FALSE;
+
+   if (!_elm_theme_object_set(obj, cur->obj, "cursor", cur->cursor_name,
+                              cur->style ? cur->style : "default"))
+     {
+        evas_object_del(cur->obj);
+        cur->obj = NULL;
+        return EINA_FALSE;
+     }
+
+   evas_object_event_callback_add(cur->obj, EVAS_CALLBACK_DEL,
+                                  _elm_cursor_obj_del, cur);
+
+   edje_object_size_min_get(cur->obj, &x, &y);
+   evas_object_resize(cur->obj, x, y);
+   return EINA_TRUE;
+}
+
+static void
+_elm_cursor_set_hot_spots(Elm_Cursor *cur)
+{
+   const char *str;
+
+   str = edje_object_data_get(cur->obj, "hot_x");
+   if (str) cur->hot_x = atoi(str);
+   else cur->hot_x = 0;
+
+   str = edje_object_data_get(cur->obj, "hot_y");
+   if (str) cur->hot_y = atoi(str);
+   else cur->hot_y = 0;
+}
+
+static void
+_elm_cursor_mouse_in(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Cursor *cur = data;
+
+   if (cur->visible) return;
+   evas_event_freeze(cur->evas);
+   cur->visible = EINA_TRUE;
+   if ((!cur->engine_only) && (!cur->use_engine))
+     {
+        if (!cur->obj)
+          _elm_cursor_obj_add(cur->eventarea, cur);
+        ecore_evas_object_cursor_set(cur->ee, cur->obj,
+                                     ELM_OBJECT_LAYER_CURSOR, cur->hot_x,
+                                     cur->hot_y);
+     }
+   else
+     {
+#ifdef HAVE_ELEMENTARY_X
+        ecore_x_window_cursor_set(cur->win, cur->cursor);
+#endif
+     }
+   evas_event_thaw(cur->evas);
+}
+
+static void
+_elm_cursor_mouse_out(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *sobj_parent;
+   Elm_Cursor *pcur = NULL;
+   Elm_Cursor *cur = data;
+
+   if (!cur->visible) return;
+   evas_event_freeze(cur->evas);
+   cur->visible = EINA_FALSE;
+
+   sobj_parent = evas_object_data_get(cur->eventarea, "elm-parent");
+   while (sobj_parent)
+     {
+        pcur = evas_object_data_get((sobj_parent), _cursor_key);
+        if ((pcur) && (pcur->visible)) break;
+        sobj_parent = evas_object_data_get(sobj_parent, "elm-parent");
+     }
+
+   if (pcur)
+     {
+        pcur->visible = EINA_FALSE;
+        evas_event_thaw(cur->evas);
+        _elm_cursor_mouse_in(pcur, NULL, NULL, NULL);
+        return;
+     }
+
+   if ((!cur->engine_only) || (!cur->use_engine))
+     {
+        ecore_evas_object_cursor_set(cur->ee, NULL, ELM_OBJECT_LAYER_CURSOR,
+                                     cur->hot_x, cur->hot_y);
+     }
+   else
+     {
+#ifdef HAVE_ELEMENTARY_X
+        ecore_x_window_cursor_set(cur->win, ECORE_X_CURSOR_X);
+#endif
+     }
+   evas_event_thaw(cur->evas);
+}
+
+static void
+_elm_cursor_del(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   elm_object_cursor_unset(obj);
+}
+
+static int
+_elm_cursor_strcmp(const void *data1, const void *data2)
+{
+   const struct _Cursor_Id *c1 = data1;
+   const struct _Cursor_Id *c2 = data2;
+   return strcmp (c1->name, c2->name);
+}
+
+static void
+_elm_cursor_cur_set(Elm_Cursor *cur)
+{
+   if (cur->engine_only)
+     {
+        INF("Using only engine cursors");
+        cur->use_engine = EINA_TRUE;
+     }
+   else if (_elm_cursor_obj_add(cur->eventarea, cur))
+     {
+        _elm_cursor_set_hot_spots(cur);
+        cur->use_engine = EINA_FALSE;
+        elm_widget_cursor_add(cur->owner, cur);
+     }
+   else
+     {
+        INF("Cursor couldn't be found on theme: %s", cur->cursor_name);
+        cur->use_engine = EINA_TRUE;
+     }
+
+   if (cur->use_engine)
+     {
+#ifdef HAVE_ELEMENTARY_X
+        struct _Cursor_Id cur_search, *cur_id;
+
+        cur_search.name = cur->cursor_name;
+        cur_id = bsearch(&(cur->cursor_name), _cursors, _cursors_count,
+                         sizeof(struct _Cursor_Id), _elm_cursor_strcmp);
+
+        cur->win = elm_win_xwindow_get(cur->eventarea);
+        if (!cur_id)
+          {
+             INF("X cursor couldn't be found: %s. Using default.",
+                 cur->cursor_name);
+             cur->cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_X);
+          }
+        else
+           cur->cursor = ecore_x_cursor_shape_get(cur_id->id);
+#endif
+     }
+}
+
+/**
+ * Set the cursor to be shown when mouse is over the object
+ *
+ * Set the cursor that will be displayed when mouse is over the
+ * object. The object can have only one cursor set to it, so if
+ * this function is called twice for an object, the previous set
+ * will be unset.
+ * If using X cursors, a definition of all the valid cursor names
+ * is listed on Elementary_Cursors.h. If an invalid name is set
+ * the default cursor will be used.
+ *
+ * This is an internal function that is used by objects with sub-items
+ * that want to provide different cursors for each of them. The @a
+ * owner object should be an elm_widget and will be used to track
+ * theme changes and to feed @a func and @a del_cb. The @a eventarea
+ * may be any object and is the one that should be used later on with
+ * elm_object_cursor apis, such as elm_object_cursor_unset().
+ *
+ * @param eventarea the object being attached a cursor.
+ * @param owner the elm_widget that owns this object, will be used to
+ *        track theme changes and to be used in @a func or @a del_cb.
+ * @param cursor the cursor name to be used.
+ *
+ * @internal
+ * @ingroup Cursors
+ */
+void
+elm_object_sub_cursor_set(Evas_Object *eventarea, Evas_Object *owner, const char *cursor)
+{
+   Elm_Cursor *cur = NULL;
+
+   cur = evas_object_data_get(eventarea, _cursor_key);
+   if (cur)
+     elm_object_cursor_unset(eventarea);
+
+   if (!cursor) return;
+
+   cur = ELM_NEW(Elm_Cursor);
+   if (!cur) return;
+
+   cur->owner = owner;
+   cur->eventarea = eventarea;
+   cur->engine_only = _elm_config->cursor_engine_only;
+   cur->visible = EINA_FALSE;
+
+   cur->cursor_name = eina_stringshare_add(cursor);
+   if (!cur->cursor_name)
+     ERR("Could not store cursor name %s", cursor);
+
+   cur->evas = evas_object_evas_get(eventarea);
+   cur->ee = ecore_evas_ecore_evas_get(cur->evas);
+
+   _elm_cursor_cur_set(cur);
+
+   evas_object_data_set(eventarea, _cursor_key, cur);
+
+   evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_IN,
+                                  _elm_cursor_mouse_in, cur);
+   evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_OUT,
+                                  _elm_cursor_mouse_out, cur);
+   evas_object_event_callback_add(eventarea, EVAS_CALLBACK_DEL,
+                                  _elm_cursor_del, cur);
+}
+
+/**
+ * Set the cursor to be shown when mouse is over the object
+ *
+ * Set the cursor that will be displayed when mouse is over the
+ * object. The object can have only one cursor set to it, so if
+ * this function is called twice for an object, the previous set
+ * will be unset.
+ * If using X cursors, a definition of all the valid cursor names
+ * is listed on Elementary_Cursors.h. If an invalid name is set
+ * the default cursor will be used.
+ *
+ * @param obj the object being set a cursor.
+ * @param cursor the cursor name to be used.
+ *
+ * @ingroup Cursors
+ */
+EAPI void
+elm_object_cursor_set(Evas_Object *obj, const char *cursor)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_object_sub_cursor_set(obj, obj, cursor);
+}
+
+/**
+ * Get the cursor to be shown when mouse is over the object
+ *
+ * @param obj an object with cursor already set.
+ * @return the cursor name.
+ *
+ * @ingroup Cursors
+ */
+EAPI const char *
+elm_object_cursor_get(const Evas_Object *obj)
+{
+   ELM_CURSOR_GET_OR_RETURN(cur, obj, NULL);
+   return cur->cursor_name;
+}
+
+/**
+ * Unset cursor for object
+ *
+ * Unset cursor for object, and set the cursor to default if the mouse
+ * was over this object.
+ *
+ * @param obj Target object
+ * @see elm_object_cursor_set()
+ *
+ * @ingroup Cursors
+ */
+EAPI void
+elm_object_cursor_unset(Evas_Object *obj)
+{
+   ELM_CURSOR_GET_OR_RETURN(cur, obj);
+
+   eina_stringshare_del(cur->cursor_name);
+   eina_stringshare_del(cur->style);
+
+   if (cur->owner)
+     elm_widget_cursor_del(cur->owner, cur);
+
+   if (cur->obj)
+     evas_object_del(cur->obj);
+
+   if (cur->visible)
+     {
+        if (!cur->use_engine)
+          ecore_evas_object_cursor_set(cur->ee, NULL, ELM_OBJECT_LAYER_CURSOR,
+                                       cur->hot_x, cur->hot_y);
+#ifdef HAVE_ELEMENTARY_X
+        else
+          ecore_x_window_cursor_set(cur->win, ECORE_X_CURSOR_X);
+#endif
+     }
+
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_IN,
+                                  _elm_cursor_mouse_in);
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_OUT,
+                                  _elm_cursor_mouse_out);
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _elm_cursor_del);
+
+   evas_object_data_del(obj, _cursor_key);
+   free(cur);
+}
+
+/**
+ * Sets a different style for this object cursor.
+ *
+ * @note before you set a style you should define a cursor with
+ *       elm_object_cursor_set()
+ *
+ * @param obj an object with cursor already set.
+ * @param style the theme style to use (default, transparent, ...)
+ *
+ * @ingroup Cursors
+ */
+EAPI void
+elm_object_cursor_style_set(Evas_Object *obj, const char *style)
+{
+   ELM_CURSOR_GET_OR_RETURN(cur, obj);
+
+   if (!eina_stringshare_replace(&cur->style, style))
+     ERR("Could not set current style=%s", style);
+
+   if (cur->use_engine) return;
+
+   if (!cur->obj)
+     {
+        if (!_elm_cursor_obj_add(obj, cur))
+          ERR("Could not create cursor object");
+        else
+          _elm_cursor_set_hot_spots(cur);
+     }
+   else
+     {
+        if (!_elm_theme_object_set(obj, cur->obj, "cursor", cur->cursor_name,
+                                   style))
+          ERR("Could not apply the theme to the cursor style=%s", style);
+        else
+          _elm_cursor_set_hot_spots(cur);
+     }
+}
+
+/**
+ * Get the style for this object cursor.
+ *
+ * @param obj an object with cursor already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a cursor set, then NULL is returned.
+ *
+ * @ingroup Cursors
+ */
+EAPI const char *
+elm_object_cursor_style_get(const Evas_Object *obj)
+{
+   ELM_CURSOR_GET_OR_RETURN(cur, obj, NULL);
+   return cur->style ? cur->style : "default";
+}
+
+/**
+ * Notify cursor should recalculate its theme.
+ * @internal
+ */
+void
+elm_cursor_theme(Elm_Cursor *cur)
+{
+   if ((!cur) || (!cur->obj)) return;
+   if (!_elm_theme_object_set(cur->eventarea, cur->obj, "cursor",
+                              cur->cursor_name, cur->style))
+     ERR("Could not apply the theme to the cursor style=%s", cur->style);
+   else
+     _elm_cursor_set_hot_spots(cur);
+}
+
+/**
+ * Set if the cursor set should be searched on the theme or should use
+ * the provided by the engine, only.
+ *
+ * @note before you set if should look on theme you should define a cursor
+ * with elm_object_cursor_set(). By default it will only look for cursors
+ * provided by the engine.
+ *
+ * @param obj an object with cursor already set.
+ * @param engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well.
+ *
+ * @ingroup Cursors
+ */
+EAPI void
+elm_object_cursor_engine_only_set(Evas_Object *obj, Eina_Bool engine_only)
+{
+   ELM_CURSOR_GET_OR_RETURN(cur, obj);
+   cur->engine_only = engine_only;
+   if (cur->obj)
+     {
+        evas_object_del(cur->obj);
+        cur->obj = NULL;
+     }
+   _elm_cursor_cur_set(cur);
+}
+
+/**
+ * Get the cursor engine only usage for this object cursor.
+ *
+ * @param obj an object with cursor already set.
+ * @return engine_only boolean to define it cursors should be looked only
+ * between the provided by the engine or searched on widget's theme as well. If
+ *         the object does not have a cursor set, then EINA_FALSE is returned.
+ *
+ * @ingroup Cursors
+ */
+EAPI Eina_Bool
+elm_object_cursor_engine_only_get(const Evas_Object *obj)
+{
+   ELM_CURSOR_GET_OR_RETURN(cur, obj, EINA_FALSE);
+   return cur->engine_only;
+}
+
+/**
+ * Get the configured cursor engine only usage
+ *
+ * This gets the globally configured exclusive usage of engine cursors.
+ *
+ * @return 1 if only engine cursors should be used
+ * @ingroup Cursors
+ */
+EAPI int
+elm_cursor_engine_only_get(void)
+{
+   return _elm_config->cursor_engine_only;
+}
+
+/**
+ * Set the configured cursor engine only usage
+ *
+ * This sets the globally configured exclusive usage of engine cursors.
+ * It won't affect cursors set before changing this value.
+ *
+ * @param engine_only If 1 only engine cursors will be enabled, if 0 will
+ * look for them on theme before.
+ * @return EINA_TRUE if value is valid and setted (0 or 1)
+ * @ingroup Cursors
+ */
+EAPI Eina_Bool
+elm_cursor_engine_only_set(int engine_only)
+{
+   if ((engine_only < 0) || (engine_only > 1)) return EINA_FALSE;
+   _elm_config->cursor_engine_only = engine_only;
+   return EINA_TRUE;
+}
diff --git a/src/lib/els_icon.c b/src/lib/els_icon.c
new file mode 100644 (file)
index 0000000..ac0b092
--- /dev/null
@@ -0,0 +1,726 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+typedef struct _Smart_Data Smart_Data;
+
+struct _Smart_Data
+{
+   Evas_Coord   x, y, w, h;
+   Evas_Object *obj;
+   int          size;
+   double       scale;
+   Eina_Bool fill_inside : 1;
+   Eina_Bool scale_up : 1;
+   Eina_Bool scale_down : 1;
+   Eina_Bool preloading : 1;
+   Eina_Bool show : 1;
+   Eina_Bool edit : 1;
+   Eina_Bool edje : 1;
+   Elm_Image_Orient orient;
+};
+
+/* local subsystem functions */
+static void _smart_reconfigure(Smart_Data *sd);
+static void _smart_init(void);
+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 _els_smart_icon_flip_horizontal(Smart_Data *sd);
+static void _els_smart_icon_flip_vertical(Smart_Data *sd);
+static void _els_smart_icon_rotate_180(Smart_Data *sd);
+static Eina_Bool _els_smart_icon_dropcb(void *,Evas_Object *, Elm_Selection_Data *);
+
+/* local subsystem globals */
+static Evas_Smart *_e_smart = NULL;
+
+/* externally accessible functions */
+Evas_Object *
+_els_smart_icon_add(Evas *evas)
+{
+   _smart_init();
+   return evas_object_smart_add(evas, _e_smart);
+}
+
+static void
+_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Smart_Data *sd = data;
+
+   sd->preloading = EINA_FALSE;
+   if (sd->show)
+     evas_object_show(sd->obj);
+}
+
+Eina_Bool
+_els_smart_icon_file_key_set(Evas_Object *obj, const char *file, const char *key)
+{
+   Smart_Data *sd;
+   Evas_Object *pclip;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+   /* smart code here */
+   if (sd->edje)
+     {
+        pclip = evas_object_clip_get(sd->obj);
+        if (sd->obj) evas_object_del(sd->obj);
+        sd->obj = evas_object_image_add(evas_object_evas_get(obj));
+        evas_object_image_scale_hint_set(sd->obj, EVAS_IMAGE_SCALE_HINT_STATIC);
+        evas_object_smart_member_add(sd->obj, obj);
+        evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_IMAGE_PRELOADED, 
+                                       _preloaded, sd);
+        evas_object_clip_set(sd->obj, pclip);
+        sd->edje = EINA_FALSE;
+     }
+   if (!sd->size)
+     evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
+   evas_object_image_file_set(sd->obj, file, key);
+   sd->preloading = EINA_TRUE;
+   sd->show = EINA_TRUE;
+   evas_object_hide(sd->obj);
+   evas_object_image_preload(sd->obj, EINA_FALSE);
+   if (evas_object_image_load_error_get(sd->obj) != EVAS_LOAD_ERROR_NONE)
+     return EINA_FALSE;
+   _smart_reconfigure(sd);
+   return EINA_TRUE;
+}
+
+Eina_Bool
+_els_smart_icon_file_edje_set(Evas_Object *obj, const char *file, const char *part)
+{
+   Smart_Data *sd;
+   Evas_Object *pclip;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+   /* smart code here */
+   if (!sd->edje)
+     {
+        pclip = evas_object_clip_get(sd->obj);
+        if (sd->obj) evas_object_del(sd->obj);
+        sd->obj = edje_object_add(evas_object_evas_get(obj));
+        evas_object_smart_member_add(sd->obj, obj);
+        if (sd->show) evas_object_show(sd->obj);
+        evas_object_clip_set(sd->obj, pclip);
+     }
+   sd->edje = EINA_TRUE;
+   if (!edje_object_file_set(sd->obj, file, part))
+     return EINA_FALSE;
+   _smart_reconfigure(sd);
+   return EINA_TRUE;
+}
+
+void
+_els_smart_icon_file_get(const Evas_Object *obj, const char **file, const char **key)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->edje)
+     edje_object_file_get(sd->obj, file, key);
+   else
+     evas_object_image_file_get(sd->obj, file, key);
+}
+
+void
+_els_smart_icon_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->edje)
+     return;
+   evas_object_image_smooth_scale_set(sd->obj, smooth);
+}
+
+Eina_Bool
+_els_smart_icon_smooth_scale_get(const Evas_Object *obj)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+   if (sd->edje)
+     return EINA_FALSE;
+   return evas_object_image_smooth_scale_get(sd->obj);
+}
+
+Evas_Object *
+_els_smart_icon_object_get(const Evas_Object *obj)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (!sd) return NULL;
+   return sd->obj;
+}
+
+void
+_els_smart_icon_size_get(const Evas_Object *obj, int *w, int *h)
+{
+   Smart_Data *sd;
+   int tw, th;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (!strcmp(evas_object_type_get(sd->obj), "edje"))
+     edje_object_size_min_get(sd->obj, &tw, &th);
+   else
+     evas_object_image_size_get(sd->obj, &tw, &th);
+   tw = ((double)tw) * sd->scale;
+   th = ((double)th) * sd->scale;
+   if (w) *w = tw;
+   if (h) *h = th;
+}
+
+void
+_els_smart_icon_fill_inside_set(Evas_Object *obj, Eina_Bool fill_inside)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (((sd->fill_inside) && (fill_inside)) ||
+       ((!sd->fill_inside) && (!fill_inside))) return;
+   sd->fill_inside = fill_inside;
+   _smart_reconfigure(sd);
+}
+
+Eina_Bool
+_els_smart_icon_fill_inside_get(const Evas_Object *obj)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+   return sd->fill_inside;
+}
+
+void
+_els_smart_icon_scale_up_set(Evas_Object *obj, Eina_Bool scale_up)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (((sd->scale_up) && (scale_up)) ||
+       ((!sd->scale_up) && (!scale_up))) return;
+   sd->scale_up = scale_up;
+   _smart_reconfigure(sd);
+}
+
+Eina_Bool
+_els_smart_icon_scale_up_get(const Evas_Object *obj)
+{
+   Smart_Data *sd; sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+   return sd->scale_up;
+}
+
+void
+_els_smart_icon_scale_down_set(Evas_Object *obj, Eina_Bool scale_down)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (((sd->scale_down) && (scale_down)) ||
+       ((!sd->scale_down) && (!scale_down))) return;
+   sd->scale_down = scale_down;
+   _smart_reconfigure(sd);
+}
+
+Eina_Bool
+_els_smart_icon_scale_down_get(const Evas_Object *obj)
+{
+   Smart_Data *sd; sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+   return sd->scale_up;
+}
+
+void
+_els_smart_icon_scale_size_set(Evas_Object *obj, int size)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->size = size;
+   if (!sd->obj) return;
+   if (sd->edje)
+     return;
+   evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
+}
+
+int
+_els_smart_icon_scale_size_get(const Evas_Object *obj)
+{
+   Smart_Data *sd; sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+   return sd->size;
+}
+
+void
+_els_smart_icon_scale_set(Evas_Object *obj, double scale)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->scale = scale;
+   _smart_reconfigure(sd);
+}
+
+double
+_els_smart_icon_scale_get(const Evas_Object *obj)
+{
+   Smart_Data *sd; sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0.0;
+   return sd->scale;
+}
+
+void
+_els_smart_icon_orient_set(Evas_Object *obj, Elm_Image_Orient orient)
+{
+   Smart_Data   *sd;
+   Evas_Object  *tmp;
+   unsigned int *data, *data2, *to, *from;
+   int           x, y, w, hw, iw, ih;
+   const char   *file, *key;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->edje)
+     return;
+
+   switch (orient)
+     {
+      case ELM_IMAGE_FLIP_HORIZONTAL:
+         _els_smart_icon_flip_horizontal(sd);
+         return;
+      case ELM_IMAGE_FLIP_VERTICAL:
+         _els_smart_icon_flip_vertical(sd);
+        return;
+      case ELM_IMAGE_ROTATE_180_CW:
+         _els_smart_icon_rotate_180(sd);
+         return;
+      default:
+         break;
+     }
+
+   evas_object_image_size_get(sd->obj, &iw, &ih);
+   evas_object_image_file_get(sd->obj, &file, &key);
+   tmp = evas_object_image_add(evas_object_evas_get(sd->obj));
+   evas_object_image_file_set(tmp, file, key);
+   data2 = evas_object_image_data_get(tmp, EINA_FALSE);
+
+   w = ih;
+   ih = iw;
+   iw = w;
+   hw = w * ih;
+
+   evas_object_image_size_set(sd->obj, iw, ih);
+   data = evas_object_image_data_get(sd->obj, EINA_TRUE);
+   switch (orient)
+     {
+      case ELM_IMAGE_FLIP_TRANSPOSE:
+        to = data;
+        hw = -hw + 1;
+        break;
+      case ELM_IMAGE_FLIP_TRANSVERSE:
+        to = data + hw - 1;
+        w = -w;
+        hw = hw - 1;
+        break;
+      case ELM_IMAGE_ROTATE_90_CW:
+        to = data + w - 1;
+        hw = -hw - 1;
+        break;
+      case ELM_IMAGE_ROTATE_90_CCW:
+        to = data + hw - w;
+        w = -w;
+        hw = hw + 1;
+        break;
+      default:
+        ERR("unknown orient %d", orient);
+        evas_object_del(tmp);
+        evas_object_image_data_set(sd->obj, data); // give it back
+        return;
+     }
+   from = data2;
+   for (x = iw; --x >= 0;)
+     {
+        for (y = ih; --y >= 0;)
+          {
+             *to = *from;
+             from++;
+             to += w;
+          }
+        to += hw;
+     }
+   sd->orient = orient;
+   evas_object_del(tmp);
+   evas_object_image_data_set(sd->obj, data);
+   evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
+   _smart_reconfigure(sd);
+}
+
+Elm_Image_Orient
+_els_smart_icon_orient_get(const Evas_Object *obj)
+{
+   Smart_Data *sd; sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+   return sd->orient;
+}
+
+/**
+ * Turns on editing through drag and drop and copy and paste.
+ */
+void
+_els_smart_icon_edit_set(Evas_Object *obj, Eina_Bool edit, Evas_Object *parent)
+{
+   Smart_Data   *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+
+   if (sd->edje)
+     {
+        printf("No editing edje objects yet (ever)\n");
+        return;
+     }
+
+   /* Unfortunately eina bool is not a bool, but a char */
+   if (edit == sd->edit) return;
+
+   sd->edit = edit;
+
+   if (sd->edit)
+     elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE, _els_smart_icon_dropcb,
+                         parent);
+   else
+     elm_drop_target_del(obj);
+}
+
+Eina_Bool
+_els_smart_icon_edit_get(const Evas_Object *obj)
+{
+   Smart_Data *sd; sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+   return sd->edit;
+}
+
+Evas_Object *
+_els_smart_icon_edje_get(Evas_Object *obj)
+{
+   Smart_Data *sd = evas_object_smart_data_get(obj);
+   if (!sd) return NULL;
+   if (!sd->edje) return NULL;
+   return sd->obj;
+}
+
+/* local subsystem globals */
+static void
+_smart_reconfigure(Smart_Data *sd)
+{
+   Evas_Coord x, y, w, h;
+
+   if (!sd->obj) return;
+   if (!strcmp(evas_object_type_get(sd->obj), "edje"))
+     {
+       w = sd->w;
+       h = sd->h;
+       x = sd->x;
+       y = sd->y;
+       evas_object_move(sd->obj, x, y);
+       evas_object_resize(sd->obj, w, h);
+     }
+   else
+     {
+        int iw = 0, ih = 0;
+
+       evas_object_image_size_get(sd->obj, &iw, &ih);
+
+       iw = ((double)iw) * sd->scale;
+       ih = ((double)ih) * sd->scale;
+
+       if (iw < 1) iw = 1;
+       if (ih < 1) ih = 1;
+
+       if (sd->fill_inside)
+         {
+            w = sd->w;
+            h = ((double)ih * w) / (double)iw;
+            if (h > sd->h)
+              {
+                 h = sd->h;
+                 w = ((double)iw * h) / (double)ih;
+              }
+         }
+       else
+         {
+            w = sd->w;
+            h = ((double)ih * w) / (double)iw;
+            if (h < sd->h)
+              {
+                 h = sd->h;
+                 w = ((double)iw * h) / (double)ih;
+              }
+         }
+       if (!sd->scale_up)
+         {
+            if ((w > iw) || (h > ih))
+              {
+                 w = iw;
+                 h = ih;
+              }
+         }
+       if (!sd->scale_down)
+         {
+            if ((w < iw) || (h < ih))
+              {
+                 w = iw;
+                 h = ih;
+              }
+         }
+       x = sd->x + ((sd->w - w) / 2);
+       y = sd->y + ((sd->h - h) / 2);
+       evas_object_move(sd->obj, x, y);
+       evas_object_image_fill_set(sd->obj, 0, 0, w, h);
+       evas_object_resize(sd->obj, w, h);
+     }
+}
+
+static void
+_smart_init(void)
+{
+   if (_e_smart) return;
+     {
+       static const Evas_Smart_Class sc =
+         {
+            "e_icon",
+              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,
+               NULL,
+               NULL,
+               NULL
+         };
+       _e_smart = evas_smart_class_new(&sc);
+     }
+}
+
+static void
+_smart_add(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = calloc(1, sizeof(Smart_Data));
+   if (!sd) return;
+   sd->obj = evas_object_image_add(evas_object_evas_get(obj));
+   evas_object_image_scale_hint_set(sd->obj, EVAS_IMAGE_SCALE_HINT_STATIC);
+   sd->x = 0;
+   sd->y = 0;
+   sd->w = 0;
+   sd->h = 0;
+   sd->fill_inside = EINA_TRUE;
+   sd->scale_up = EINA_TRUE;
+   sd->scale_down = EINA_TRUE;
+   sd->size = 64;
+   sd->scale = 1.0;
+   evas_object_smart_member_add(sd->obj, obj);
+   evas_object_smart_data_set(obj, sd);
+   evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_IMAGE_PRELOADED,
+                                  _preloaded, sd);
+}
+
+static void
+_smart_del(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   evas_object_del(sd->obj);
+   free(sd);
+}
+
+static void
+_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if ((sd->x == x) && (sd->y == y)) return;
+   sd->x = x;
+   sd->y = y;
+   _smart_reconfigure(sd);
+}
+
+static void
+_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if ((sd->w == w) && (sd->h == h)) return;
+   sd->w = w;
+   sd->h = h;
+   _smart_reconfigure(sd);
+}
+
+static void
+_smart_show(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->show = EINA_TRUE;
+   if (!sd->preloading)
+     evas_object_show(sd->obj);
+}
+
+static void
+_smart_hide(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   sd->show = EINA_FALSE;
+   evas_object_hide(sd->obj);
+}
+
+static void
+_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   evas_object_color_set(sd->obj, r, g, b, a);
+}
+
+static void
+_smart_clip_set(Evas_Object *obj, Evas_Object * clip)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   evas_object_clip_set(sd->obj, clip);
+}
+
+static void
+_smart_clip_unset(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   evas_object_clip_unset(sd->obj);
+}
+
+static void
+_els_smart_icon_flip_horizontal(Smart_Data *sd)
+{
+   unsigned int   *data;
+   unsigned int   *p1, *p2, tmp;
+   int             x, y, iw, ih;
+
+   evas_object_image_size_get(sd->obj, &iw, &ih);
+   data = evas_object_image_data_get(sd->obj, EINA_TRUE);
+
+   for (y = 0; y < ih; y++)
+     {
+        p1 = data + (y * iw);
+        p2 = data + ((y + 1) * iw) - 1;
+        for (x = 0; x < (iw >> 1); x++)
+          {
+             tmp = *p1;
+             *p1 = *p2;
+             *p2 = tmp;
+             p1++;
+             p2--;
+          }
+     }
+
+   evas_object_image_data_set(sd->obj, data);
+   evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
+   _smart_reconfigure(sd);
+}
+
+static void
+_els_smart_icon_flip_vertical(Smart_Data *sd)
+{
+   unsigned int   *data;
+   unsigned int   *p1, *p2, tmp;
+   int             x, y, iw, ih;
+
+   evas_object_image_size_get(sd->obj, &iw, &ih);
+   data = evas_object_image_data_get(sd->obj, EINA_TRUE);
+
+   for (y = 0; y < (ih >> 1); y++)
+     {
+        p1 = data + (y * iw);
+        p2 = data + ((ih - 1 - y) * iw);
+        for (x = 0; x < iw; x++)
+          {
+             tmp = *p1;
+             *p1 = *p2;
+             *p2 = tmp;
+             p1++;
+             p2++;
+          }
+     }
+
+   evas_object_image_data_set(sd->obj, data);
+   evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
+   _smart_reconfigure(sd);
+}
+
+static void
+_els_smart_icon_rotate_180(Smart_Data *sd)
+{
+   unsigned int   *data;
+   unsigned int   *p1, *p2, tmp;
+   int             x, hw, iw, ih;
+
+   evas_object_image_size_get(sd->obj, &iw, &ih);
+   data = evas_object_image_data_get(sd->obj, 1);
+
+   hw = iw * ih;
+   x = (hw / 2);
+   p1 = data;
+   p2 = data + hw - 1;
+   for (; --x > 0;)
+     {
+        tmp = *p1;
+        *p1 = *p2;
+        *p2 = tmp;
+        p1++;
+        p2--;
+     }
+   evas_object_image_data_set(sd->obj, data);
+   evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
+   _smart_reconfigure(sd);
+}
+
+static Eina_Bool
+_els_smart_icon_dropcb(void *elmobj,Evas_Object *obj, Elm_Selection_Data *drop)
+{
+   _els_smart_icon_file_key_set(obj, drop->data, NULL);
+   evas_object_smart_callback_call(elmobj, "drop", drop->data);
+
+   return EINA_TRUE;
+}
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/src/lib/els_icon.h b/src/lib/els_icon.h
new file mode 100644 (file)
index 0000000..f4325c8
--- /dev/null
@@ -0,0 +1,23 @@
+Evas_Object *_els_smart_icon_add              (Evas *evas);
+Eina_Bool    _els_smart_icon_file_key_set     (Evas_Object *obj, const char *file, const char *key);
+Eina_Bool    _els_smart_icon_file_edje_set    (Evas_Object *obj, const char *file, const char *part);
+void         _els_smart_icon_file_get         (const Evas_Object *obj, const char **file, const char **key);
+void         _els_smart_icon_smooth_scale_set (Evas_Object *obj, Eina_Bool smooth);
+Eina_Bool    _els_smart_icon_smooth_scale_get (const Evas_Object *obj);
+Evas_Object *_els_smart_icon_object_get       (const Evas_Object *obj);
+void         _els_smart_icon_size_get         (const Evas_Object *obj, int *w, int *h);
+void         _els_smart_icon_fill_inside_set  (Evas_Object *obj, Eina_Bool fill_inside);
+Eina_Bool    _els_smart_icon_fill_inside_get  (const Evas_Object *obj);
+void         _els_smart_icon_scale_up_set     (Evas_Object *obj, Eina_Bool scale_up);
+Eina_Bool    _els_smart_icon_scale_up_get     (const Evas_Object *obj);
+void         _els_smart_icon_scale_down_set   (Evas_Object *obj, Eina_Bool scale_down);
+Eina_Bool    _els_smart_icon_scale_down_get   (const Evas_Object *obj);
+void         _els_smart_icon_scale_size_set   (Evas_Object *obj, int size);
+int          _els_smart_icon_scale_size_get   (const Evas_Object *obj);
+void         _els_smart_icon_scale_set        (Evas_Object *obj, double scale);
+double       _els_smart_icon_scale_get        (const Evas_Object *obj);
+void         _els_smart_icon_orient_set       (Evas_Object *obj, Elm_Image_Orient orient);
+Elm_Image_Orient _els_smart_icon_orient_get   (const Evas_Object *obj);
+void         _els_smart_icon_edit_set         (Evas_Object *obj, Eina_Bool, Evas_Object *parent);
+Eina_Bool    _els_smart_icon_edit_get         (const Evas_Object *obj);
+Evas_Object *_els_smart_icon_edje_get(Evas_Object *obj);
diff --git a/src/lib/els_pan.c b/src/lib/els_pan.c
new file mode 100644 (file)
index 0000000..436d287
--- /dev/null
@@ -0,0 +1,285 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define SMART_NAME "elm_pan"
+#define API_ENTRY 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 Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
+typedef struct _Smart_Data Smart_Data;
+
+struct _Smart_Data
+{
+   Evas_Object *smart_obj;
+   Evas_Object *child_obj;
+   Evas_Coord   x, y, w, h;
+   Evas_Coord   child_w, child_h, px, py;
+};
+
+/* local subsystem functions */
+static void _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _smart_child_resize_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static void _smart_reconfigure(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 *
+_elm_smart_pan_add(Evas *evas)
+{
+   _smart_init();
+   return evas_object_smart_add(evas, _smart);
+}
+
+void
+_elm_smart_pan_child_set(Evas_Object *obj, Evas_Object *child)
+{
+   API_ENTRY return;
+   if (child == sd->child_obj) return;
+   if (sd->child_obj)
+     {
+       evas_object_clip_unset(sd->child_obj);
+       evas_object_smart_member_del(sd->child_obj);
+        evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_FREE, _smart_child_del_hook, sd);
+       evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_RESIZE, _smart_child_resize_hook, sd);
+       sd->child_obj = NULL;
+     }
+   if (child)
+     {
+       Evas_Coord w, h;
+       int r, g, b, a;
+
+       sd->child_obj = child;
+       evas_object_smart_member_add(sd->child_obj, sd->smart_obj);
+       evas_object_geometry_get(sd->child_obj, NULL, NULL, &w, &h);
+       sd->child_w = w;
+       sd->child_h = h;
+       evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _smart_child_del_hook, sd);
+       evas_object_event_callback_add(child, EVAS_CALLBACK_RESIZE, _smart_child_resize_hook, sd);
+       evas_object_color_get(sd->smart_obj, &r, &g, &b, &a);
+       evas_object_color_set(sd->child_obj, r, g, b, a);
+       evas_object_clip_set(sd->child_obj, evas_object_clip_get(sd->smart_obj));
+       if (evas_object_visible_get(sd->smart_obj)) evas_object_show(sd->child_obj);
+       else evas_object_hide(sd->child_obj);
+       _smart_reconfigure(sd);
+     }
+   evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
+}
+
+Evas_Object *
+_elm_smart_pan_child_get(Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   return sd->child_obj;
+}
+
+void
+_elm_smart_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   API_ENTRY return;
+//   if (x > (sd->child_w - sd->w)) x = sd->child_w - sd->w;
+//   if (y > (sd->child_h - sd->h)) y = sd->child_h - sd->h;
+//   if (x < 0) x = 0;
+//   if (y < 0) y = 0;
+   if ((x == sd->px) && (y == sd->py)) return;
+   sd->px = x;
+   sd->py = y;
+   _smart_reconfigure(sd);
+   evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
+}
+
+void
+_elm_smart_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   API_ENTRY return;
+   if (x) *x = sd->px;
+   if (y) *y = sd->py;
+}
+
+void
+_elm_smart_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   API_ENTRY return;
+   if (x)
+     {
+       if (sd->w < sd->child_w) *x = sd->child_w - sd->w;
+       else *x = 0;
+     }
+   if (y)
+     {
+       if (sd->h < sd->child_h) *y = sd->child_h - sd->h;
+       else *y = 0;
+     }
+}
+
+void
+_elm_smart_pan_min_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   API_ENTRY return;
+   if (x)
+      *x = 0;
+   if (y)
+      *y = 0;
+}
+
+void
+_elm_smart_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   API_ENTRY return;
+   if (w) *w = sd->child_w;
+   if (h) *h = sd->child_h;
+}
+
+/* local subsystem functions */
+static void
+_smart_child_del_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Smart_Data *sd;
+
+   sd = data;
+   sd->child_obj = NULL;
+   evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
+}
+
+static void
+_smart_child_resize_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Smart_Data *sd;
+   Evas_Coord w, h;
+
+   sd = data;
+   evas_object_geometry_get(sd->child_obj, NULL, NULL, &w, &h);
+   if ((w != sd->child_w) || (h != sd->child_h))
+     {
+       sd->child_w = w;
+       sd->child_h = h;
+       _smart_reconfigure(sd);
+     }
+   evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
+}
+
+static void
+_smart_reconfigure(Smart_Data *sd)
+{
+   evas_object_move(sd->child_obj, sd->x - sd->px, sd->y - sd->py);
+}
+
+static void
+_smart_add(Evas_Object *obj)
+{
+   Smart_Data *sd;
+
+   sd = calloc(1, sizeof(Smart_Data));
+   if (!sd) return;
+   sd->smart_obj = obj;
+   sd->x = 0;
+   sd->y = 0;
+   sd->w = 0;
+   sd->h = 0;
+   evas_object_smart_data_set(obj, sd);
+}
+
+static void
+_smart_del(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   _elm_smart_pan_child_set(obj, NULL);
+   free(sd);
+}
+
+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);
+   evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
+}
+
+static void
+_smart_show(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   evas_object_show(sd->child_obj);
+}
+
+static void
+_smart_hide(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   evas_object_hide(sd->child_obj);
+}
+
+static void
+_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
+{
+   INTERNAL_ENTRY;
+   evas_object_color_set(sd->child_obj, r, g, b, a);
+}
+
+static void
+_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
+{
+   INTERNAL_ENTRY;
+   evas_object_clip_set(sd->child_obj, clip);
+}
+
+static void
+_smart_clip_unset(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   evas_object_clip_unset(sd->child_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,
+              NULL,
+              NULL,
+              NULL
+         };
+       _smart = evas_smart_class_new(&sc);
+     }
+}
+
diff --git a/src/lib/els_pan.h b/src/lib/els_pan.h
new file mode 100644 (file)
index 0000000..cb64fa1
--- /dev/null
@@ -0,0 +1,8 @@
+Evas_Object *_elm_smart_pan_add            (Evas *evas);
+void         _elm_smart_pan_child_set      (Evas_Object *obj, Evas_Object *child);
+Evas_Object *_elm_smart_pan_child_get      (Evas_Object *obj);
+void         _elm_smart_pan_set            (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+void         _elm_smart_pan_get            (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void         _elm_smart_pan_max_get        (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void         _elm_smart_pan_min_get        (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void         _elm_smart_pan_child_size_get (Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
diff --git a/src/lib/els_scroller.c b/src/lib/els_scroller.c
new file mode 100644 (file)
index 0000000..85d002e
--- /dev/null
@@ -0,0 +1,2606 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define SMART_NAME "els_scroller"
+#define API_ENTRY 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 Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
+typedef struct _Smart_Data Smart_Data;
+
+#define EVTIME 1
+//#define SCROLLDBG 1
+
+struct _Smart_Data
+{
+   Evas_Coord   x, y, w, h;
+   Evas_Coord   wx, wy, ww, wh; /* Last "wanted" geometry */
+
+   Evas_Object *smart_obj;
+   Evas_Object *child_obj;
+   Evas_Object *pan_obj;
+   Evas_Object *edje_obj;
+   Evas_Object *event_obj;
+
+   Evas_Object *widget;
+   
+   Elm_Smart_Scroller_Policy hbar_flags, vbar_flags;
+
+   struct {
+      Evas_Coord x, y;
+      Evas_Coord sx, sy;
+      Evas_Coord dx, dy;
+      Evas_Coord pdx, pdy;
+      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;
+      double extra_time;
+      Evas_Coord hold_x, hold_y;
+      Ecore_Animator *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;
+      int hdir, vdir;
+      unsigned char now : 1;
+      unsigned char cancelled : 1;
+      unsigned char hold : 1;
+      unsigned char hold_parent : 1;
+      unsigned char want_dragged : 1;
+      unsigned char dragged : 1;
+      unsigned char dragged_began : 1;
+      unsigned char dir_x : 1;
+      unsigned char dir_y : 1;
+      unsigned char locked : 1;
+      unsigned char bounce_x_hold : 1;
+      unsigned char bounce_y_hold : 1;
+      unsigned char scroll : 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 (*min_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;
+   unsigned char momentum_animator_disabled :1;
+   unsigned char bounce_animator_disabled :1;
+};
+
+/* 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_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(Smart_Data *sd);
+static void _smart_scrollbar_reset(Smart_Data *sd);
+static int  _smart_scrollbar_bar_h_visibility_adjust(Smart_Data *sd);
+static int  _smart_scrollbar_bar_v_visibility_adjust(Smart_Data *sd);
+static void _smart_scrollbar_bar_visibility_adjust(Smart_Data *sd);
+static void _smart_scrollbar_size_adjust(Smart_Data *sd);
+static void _smart_reconfigure(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 *
+elm_smart_scroller_add(Evas *evas)
+{
+   _smart_init();
+   return evas_object_smart_add(evas, _smart);
+}
+
+void
+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;
+   sd->wx = sd->wy = sd->ww = sd->wh = 0;
+   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.min_get = _elm_smart_pan_min_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
+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_min_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;
+
+   elm_smart_scroller_child_set(obj, NULL);
+
+   if (sd->pan_obj)
+     {
+        evas_object_smart_callback_del(sd->pan_obj, "changed", _smart_pan_changed_hook);
+        evas_object_smart_callback_del(sd->pan_obj, "pan_changed", _smart_pan_pan_changed_hook);
+     }
+
+   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.min_get = pan_min_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
+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_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
+   else if (sd->hbar_flags == ELM_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_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
+   else if (sd->vbar_flags == ELM_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");
+}
+
+Eina_Bool
+elm_smart_scroller_momentum_animator_disabled_get(Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->momentum_animator_disabled;
+}
+
+void
+elm_smart_scroller_momentum_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
+{
+   API_ENTRY return;
+   sd->momentum_animator_disabled = disabled;
+   if (sd->momentum_animator_disabled)
+     {
+        if (sd->down.momentum_animator)
+          {
+             ecore_animator_del(sd->down.momentum_animator);
+             sd->down.momentum_animator = NULL;
+          }
+     }
+}
+
+Eina_Bool
+elm_smart_scroller_bounce_animator_disabled_get(Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->bounce_animator_disabled;
+}
+
+void
+elm_smart_scroller_bounce_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
+{
+   API_ENTRY return;
+   sd->bounce_animator_disabled = disabled;
+   if (sd->bounce_animator_disabled)
+     {
+        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;
+          }
+     }
+}
+
+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)
+{
+   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;
+        elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+        sd->scrollto.x.animator = NULL;
+        if ((!sd->scrollto.y.animator) && (!sd->down.bounce_y_animator))
+          _smart_anim_stop(sd->smart_obj);
+        return ECORE_CALLBACK_CANCEL;
+     }
+   elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_smart_momentum_end(Smart_Data *sd)
+{
+   if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator)) return;
+   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;
+        sd->down.pdx = 0;
+        sd->down.pdy = 0;
+     }
+}
+
+static void
+_smart_scrollto_x(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)
+     {
+        elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+        x = pos_x;
+        elm_smart_scroller_child_region_set(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;
+   elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   elm_smart_scroller_child_region_set(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;
+        _smart_momentum_end(sd);
+     }
+   sd->bouncemex = 0;
+}
+
+static Eina_Bool
+_smart_scrollto_y_animator(void *data)
+{
+   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;
+        elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+        sd->scrollto.y.animator = NULL;
+        if ((!sd->scrollto.x.animator) && (!sd->down.bounce_x_animator))
+          _smart_anim_stop(sd->smart_obj);
+        return ECORE_CALLBACK_CANCEL;
+     }
+   elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_smart_scrollto_y(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)
+     {
+        elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+        y = pos_y;
+        elm_smart_scroller_child_region_set(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;
+   elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   elm_smart_scroller_child_region_set(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;
+        _smart_momentum_end(sd);
+     }
+   sd->bouncemey = 0;
+}
+
+static Eina_Bool
+_smart_do_page(Smart_Data *sd)
+{
+   if ((sd->pagerel_h == 0.0) && (!sd->pagesize_h) &&
+       (sd->pagerel_v == 0.0) && (!sd->pagesize_v))
+     return EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static Evas_Coord
+_smart_page_x_get(Smart_Data *sd, int offset)
+{
+   Evas_Coord x, y, w, h, cw, ch, minx = 0;
+
+   elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+   sd->pan_func.min_get(sd->pan_obj, &minx, NULL);
+
+   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 < minx) x = minx;
+   else if ((x + w) > cw) x = cw - w;
+   return x;
+}
+
+static Evas_Coord
+_smart_page_y_get(Smart_Data *sd, int offset)
+{
+   Evas_Coord x, y, w, h, cw, ch, miny = 0;
+
+   elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+   sd->pan_func.min_get(sd->pan_obj, NULL, &miny);
+
+   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 < miny) y = miny;
+   else if ((y + h) > ch) y = ch - h;
+   return y;
+}
+
+static void
+_smart_page_adjust(Smart_Data *sd)
+{
+   Evas_Coord x, y, w, h;
+
+   if (!_smart_do_page(sd)) return;
+
+   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);
+
+   elm_smart_scroller_child_region_set(sd->smart_obj, x, y, w, h);
+}
+
+static Eina_Bool
+_smart_bounce_x_animator(void *data)
+{
+   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));
+        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;
+        if (!sd->down.cancelled)
+          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;
+             else if ((!sd->down.bounce_y_animator) && 
+                 (!sd->scrollto.y.animator))
+               _smart_anim_stop(sd->smart_obj);
+             sd->down.bounce_x_animator = NULL;
+             sd->down.pdx = 0;
+             sd->bouncemex = 0;
+             _smart_momentum_end(sd);
+             return ECORE_CALLBACK_CANCEL;
+          }
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_smart_bounce_y_animator(void *data)
+{
+   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));
+        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;
+        if (!sd->down.cancelled)
+          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;
+             else if ((!sd->down.bounce_x_animator) && 
+                 (!sd->scrollto.y.animator))
+               _smart_anim_stop(sd->smart_obj);
+             sd->down.bounce_y_animator = NULL;
+             sd->down.pdy = 0;
+             sd->bouncemey = 0;
+             _smart_momentum_end(sd);
+             return ECORE_CALLBACK_CANCEL;
+          }
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+#define LEFT 0
+#define RIGHT 1
+#define UP 2
+#define DOWN 3
+static Eina_Bool
+can_scroll(Smart_Data *sd, int dir)
+{
+   Evas_Coord mx = 0, my = 0, px = 0, py = 0, minx = 0, miny = 0;
+
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   switch (dir)
+     {
+     case LEFT:
+        if (px > minx) return EINA_TRUE;
+        break;
+     case RIGHT:
+        if ((px - minx) < mx) return EINA_TRUE;
+        break;
+     case UP:
+        if (py > miny) return EINA_TRUE;
+        break;
+     case DOWN:
+        if ((py - miny) < my) return EINA_TRUE;
+        break;
+     default:
+        break;
+     }
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_smart_momentum_animator(void *data)
+{
+   Smart_Data *sd;
+   double t, dt, p;
+   Evas_Coord x, y, dx, dy, px, py, maxx, maxy, minx, miny;
+
+   sd = data;
+   t = ecore_loop_time_get();
+   dt = t - sd->down.anim_start;
+   if (dt >= 0.0)
+     {
+        /*
+        if (sd->down.hold_parent)
+          {
+             if ((sd->down.dir_x) && !can_scroll(sd, sd->down.hdir))
+               {
+                  sd->down.dir_x = 0;
+               }
+             if ((sd->down.dir_y) && !can_scroll(sd, sd->down.vdir))
+               {
+                  sd->down.dir_y = 0;
+               }
+          }
+        if ((!sd->down.dir_x) && (!sd->down.dir_y))
+          {
+             sd->down.cancelled = 1;
+          }
+         */
+       dt = dt / (_elm_config->thumbscroll_friction + sd->down.extra_time);
+       if (dt > 1.0) dt = 1.0;
+       p = 1.0 - ((1.0 - dt) * (1.0 - dt));
+       dx = (sd->down.dx * (_elm_config->thumbscroll_friction + sd->down.extra_time) * p);
+       dy = (sd->down.dy * (_elm_config->thumbscroll_friction + sd->down.extra_time) * p);
+        sd->down.ax = dx;
+        sd->down.ay = dy;
+       x = sd->down.sx - dx;
+       y = sd->down.sy - dy;
+        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;
+          }
+       elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+        sd->pan_func.max_get(sd->pan_obj, &maxx, &maxy);
+        sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+        if ((dt >= 1.0) || 
+            ((sd->down.bounce_x_hold) && (sd->down.bounce_y_hold)))
+         {
+             _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;
+             sd->down.pdx = 0;
+             sd->down.pdy = 0;
+            return ECORE_CALLBACK_CANCEL;
+         }
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+bounce_eval(Smart_Data *sd)
+{
+   Evas_Coord mx, my, px, py, bx, by, b2x, b2y, minx = 0, miny = 0;
+
+   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_animator_del(sd->down.hold_animator);
+        sd->down.hold_animator = NULL;
+     }
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   bx = px;
+   by = py;
+   if (px < minx) px = minx;
+   if ((px - minx) > mx) px = mx + minx;
+   if (py < miny) py = miny;
+   if ((py - miny) > my) py = my + miny;
+   b2x = px;
+   b2y = py;
+   if ((!sd->widget) || 
+       (!elm_widget_drag_child_locked_x_get(sd->widget)))
+     {
+        if (!sd->down.bounce_x_animator && !sd->bounce_animator_disabled)
+          {
+             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->widget) || 
+       (!elm_widget_drag_child_locked_y_get(sd->widget)))
+     {
+        if (!sd->down.bounce_y_animator && !sd->bounce_animator_disabled)
+          {
+             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
+elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Evas_Coord mx = 0, my = 0, px, py, minx = 0, miny = 0;
+   double vx, vy;
+
+   API_ENTRY return;
+   // FIXME: allow for bounce outside of range
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+   if (mx > 0) vx = (double)(x - minx) / (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 - miny) / (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 < minx) x = minx;
+        if ((x - minx) > mx) x = mx + minx;
+        if (y < miny) y = miny;
+        if ((y - miny) > my) y = my + miny;
+     }
+
+   if (!sd->bounce_horiz)
+     {
+        if (x < minx) x = minx;
+        if ((x - minx) > mx) x = mx + minx;
+     }
+   if (!sd->bounce_vert)
+     {
+        if (y < miny) y = miny;
+        if (y - miny > my) y = my + miny;
+     }
+
+   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 < minx) || (x > (mx + minx)))
+          {
+             sd->bouncemex = 1;
+             bounce_eval(sd);
+          }
+     }
+   if (!sd->down.bounce_y_animator)
+     {
+        if ((y < miny) || (y > my + miny))
+          {
+             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 == minx)
+          evas_object_smart_callback_call(obj, "edge,left", NULL);
+        if (x == (mx + minx))
+          evas_object_smart_callback_call(obj, "edge,right", NULL);
+     }
+   if ((y != py)/* && (!sd->bouncemey)*/)
+     {
+        if (y == miny)
+          evas_object_smart_callback_call(obj, "edge,top", NULL);
+        if (y == my + miny)
+          evas_object_smart_callback_call(obj, "edge,bottom", NULL);
+     }
+}
+
+void
+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);
+}
+
+/* "internal_call" actually toggles whether we should save the coords and do
+ * extra "speedup" checks, or not. */
+static void
+_elm_smart_scroller_child_region_show_internal(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool internal_call)
+{
+   Evas_Coord mx = 0, my = 0, cw = 0, ch = 0, px = 0, py = 0, nx, ny, minx = 0, miny = 0;
+
+   API_ENTRY return;
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+   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 (!internal_call)
+     {
+        sd->wx = x;
+        sd->wy = y;
+        sd->ww = w;
+        sd->wh = h;
+        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_animator_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;
+        sd->down.pdx = 0;
+        sd->down.pdy = 0;
+     }
+   elm_smart_scroller_child_pos_set(obj, nx, ny);
+}
+
+/* Set should be used for calculated positions, for example, when we move
+ * because of an animation or because this is the correct position after
+ * constraints. */
+void
+elm_smart_scroller_child_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   _elm_smart_scroller_child_region_show_internal(obj, x, y, w, h, EINA_TRUE);
+}
+
+/* Set should be used for setting the wanted position, for example a user scroll
+ * or moving the cursor in an entry. */
+void
+elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   _elm_smart_scroller_child_region_show_internal(obj, x, y, w, h, EINA_FALSE);
+}
+
+void
+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
+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
+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
+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
+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
+elm_smart_scroller_policy_set(Evas_Object *obj, Elm_Smart_Scroller_Policy hbar, Elm_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_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
+   else if (sd->hbar_flags == ELM_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_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
+   else if (sd->vbar_flags == ELM_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
+elm_smart_scroller_policy_get(Evas_Object *obj, Elm_Smart_Scroller_Policy *hbar, Elm_Smart_Scroller_Policy *vbar)
+{
+   API_ENTRY return;
+   if (hbar) *hbar = sd->hbar_flags;
+   if (vbar) *vbar = sd->vbar_flags;
+}
+
+Evas_Object *
+elm_smart_scroller_edje_object_get(Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   return sd->edje_obj;
+}
+
+void
+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
+elm_smart_scroller_single_dir_get(Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->one_dir_at_a_time;
+}
+
+void
+elm_smart_scroller_object_theme_set(Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style)
+{
+   API_ENTRY return;
+   Evas_Coord mw, mh;
+   _elm_theme_object_set(parent, sd->edje_obj, clas, group, style);
+   edje_object_scale_set(sd->edje_obj, elm_widget_scale_get(parent) * _elm_config->scale);
+   if (sd->pan_obj)
+     edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
+   mw = mh = -1;
+   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+   if (edje_object_part_exists(sd->edje_obj, "elm.scrollbar.base"))
+     {
+        Evas_Object *base;
+        base = edje_object_part_swallow_get(sd->edje_obj, "elm.scrollbar.base");
+        if (!base)
+          {
+             base = evas_object_rectangle_add(evas_object_evas_get(sd->edje_obj));
+             evas_object_color_set(base, 0, 0, 0, 0);
+             edje_object_part_swallow(sd->edje_obj, "elm.scrollbar.base", base);
+          }
+        if (!_elm_config->thumbscroll_enable)
+           evas_object_size_hint_min_set(base, mw, mh);
+     }
+   sd->vbar_visible = !sd->vbar_visible;
+   sd->hbar_visible = !sd->hbar_visible;
+   _smart_scrollbar_bar_visibility_adjust(sd);
+}
+
+void
+elm_smart_scroller_hold_set(Evas_Object *obj, Eina_Bool hold)
+{
+   API_ENTRY return;
+   sd->hold = hold;
+}
+
+void
+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
+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
+elm_smart_scroller_bounce_allow_get(const Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert)
+{
+   API_ENTRY return;
+   *horiz = sd->bounce_horiz;
+   *vert = sd->bounce_vert;
+}
+
+void
+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
+elm_smart_scroller_paging_get(Evas_Object *obj, double *pagerel_h, double *pagerel_v, Evas_Coord *pagesize_h, Evas_Coord *pagesize_v)
+{
+   API_ENTRY return;
+   if(pagerel_h) *pagerel_h = sd->pagerel_h;
+   if(pagerel_v) *pagerel_v = sd->pagerel_v;
+   if(pagesize_h) *pagesize_h = sd->pagesize_h;
+   if(pagesize_v) *pagesize_v = sd->pagesize_v;
+}
+
+void
+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, minx = 0, miny = 0;
+
+   API_ENTRY return;
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+   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_animator_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;
+        sd->down.pdx = 0;
+        sd->down.pdy = 0;
+     }
+   x = nx;
+   if (x < minx) x = minx;
+   else if ((x + w) > cw) x = cw - w;
+   _smart_scrollto_x(sd, _elm_config->bring_in_scroll_friction, x);
+   y = ny;
+   if (y < miny) y = miny;
+   else if ((y + h) > ch) y = ch - h;
+   _smart_scrollto_y(sd, _elm_config->bring_in_scroll_friction, y);
+}
+
+void
+elm_smart_scroller_widget_set(Evas_Object *obj, Evas_Object *wid)
+{
+   API_ENTRY return;
+   sd->widget = wid;
+}
+
+/* local subsystem functions */
+static void
+_smart_edje_drag_v_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   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 __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   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 __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+}
+
+static void
+_smart_edje_drag_h_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   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 __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   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 __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+}
+
+static void
+_smart_child_del_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   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 __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Coord x, y;
+   Evas_Coord w, h;
+   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);
+        elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+     }
+}
+
+static void
+_smart_pan_pan_changed_hook(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Coord x, y;
+   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;
+     }
+   elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+}
+
+static void
+_smart_event_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Wheel *ev;
+   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;
+   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)
+     y += ev->z * sd->step.y;
+   else if (ev->direction == 1)
+     x += ev->z * sd->step.x;
+
+   if ((!sd->hold) && (!sd->freeze))
+     {
+        sd->wx = x;
+        sd->wy = y;
+        elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &sd->ww, &sd->wh);
+        elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+     }
+}
+
+static void
+_smart_event_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev;
+   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)
+     {
+        sd->down.hold = 0;
+        if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
+            (sd->down.momentum_animator) || (sd->scrollto.x.animator) ||
+            (sd->scrollto.y.animator))
+          {
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL | EVAS_EVENT_FLAG_ON_HOLD;
+             sd->down.scroll = 1;
+             sd->down.hold = 1;
+             _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_animator_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.x = ev->canvas.x;
+            sd->down.y = ev->canvas.y;
+            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;
+         }
+        sd->down.dragged_began = 0;
+        sd->down.hold_parent = 0;
+        sd->down.cancelled = 0;
+     }
+}
+
+static Eina_Bool
+_smart_hold_animator(void *data)
+{
+   Smart_Data *sd = data;
+   Evas_Coord ox, oy;
+   
+   elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
+   if (sd->down.dir_x)
+     {
+        if ((!sd->widget) || 
+            (!elm_widget_drag_child_locked_x_get(sd->widget)))
+          {
+             ox = sd->down.hold_x;
+          }
+     }
+   if (sd->down.dir_y)
+     {
+        if ((!sd->widget) || 
+            (!elm_widget_drag_child_locked_y_get(sd->widget)))
+          {
+             oy = sd->down.hold_y;
+          }
+     }
+   elm_smart_scroller_child_pos_set(sd->smart_obj, ox, oy);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_smart_event_post_up(void *data, Evas *e __UNUSED__)
+{
+   Smart_Data *sd = data;
+   if (sd->widget)
+     {
+        if (sd->down.dragged)
+          {
+             elm_widget_drag_lock_x_set(sd->widget, 0);
+             elm_widget_drag_lock_y_set(sd->widget, 0);
+          }
+     }
+   return EINA_TRUE;
+}
+
+static void
+_smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev;
+   Smart_Data *sd;
+   Evas_Coord x = 0, y = 0, ox = 0, oy = 0;
+
+   sd = data;
+   ev = event_info;
+   sd->down.hold_parent = 0;
+//   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
+   evas_post_event_callback_push(e, _smart_event_post_up, sd);
+   // 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_threshold) &&
+                                (!sd->freeze))
+                              {
+                                 sd->down.dx = ((double)dx / at);
+                                 sd->down.dy = ((double)dy / at);
+                                 if (((sd->down.dx > 0) && (sd->down.pdx > 0)) ||
+                                     ((sd->down.dx < 0) && (sd->down.pdx < 0)))
+                                   sd->down.dx += (double)sd->down.pdx * 1.5; // FIXME: * 1.5 - probably should be config
+                                 if (((sd->down.dy > 0) && (sd->down.pdy > 0)) ||
+                                     ((sd->down.dy < 0) && (sd->down.pdy < 0)))
+                                   sd->down.dy += (double)sd->down.pdy * 1.5; // FIXME: * 1.5 - probably should be config
+                                 if (((sd->down.dx > 0) && (sd->down.pdx > 0)) ||
+                                     ((sd->down.dx < 0) && (sd->down.pdx < 0)) ||
+                                     ((sd->down.dy > 0) && (sd->down.pdy > 0)) ||
+                                     ((sd->down.dy < 0) && (sd->down.pdy < 0)))
+                                  {
+                                    double t = ecore_loop_time_get();
+                                    double dt = t - sd->down.anim_start;
+                                    
+                                    if (dt < 0.0) dt = 0.0;
+                                    else if (dt > _elm_config->thumbscroll_friction)
+                                      dt = _elm_config->thumbscroll_friction;
+                                    sd->down.extra_time = _elm_config->thumbscroll_friction - dt;
+                                  }
+                                 else
+                                  sd->down.extra_time = 0.0;
+                                 sd->down.pdx = sd->down.dx;
+                                 sd->down.pdy = sd->down.dy;
+                                 ox = -sd->down.dx;
+                                 oy = -sd->down.dy;
+                                 if (!_smart_do_page(sd))
+                                   {
+                                      if (!sd->down.momentum_animator && !sd->momentum_animator_disabled)
+                                        {
+                                           sd->down.momentum_animator = ecore_animator_add(_smart_momentum_animator, sd);
+                                           ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
+                                           _smart_anim_start(sd->smart_obj);
+                                        }
+                                      sd->down.anim_start = ecore_loop_time_get();
+                                      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_animator_del(sd->down.hold_animator);
+                            sd->down.hold_animator = NULL;
+                         }
+                    }
+                  else
+                    {
+                       sd->down.pdx = 0;
+                       sd->down.pdy = 0;
+                    }
+                  evas_event_feed_hold(e, 0, ev->timestamp, ev->data);
+                  if (_smart_do_page(sd))
+                    {
+                       Evas_Coord pgx, pgy;
+
+                       elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+                       if ((!sd->widget) || 
+                           (!elm_widget_drag_child_locked_x_get(sd->widget)))
+                         {
+                            pgx = _smart_page_x_get(sd, ox);
+                            if (pgx != x) 
+                              {
+                                 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
+                                 _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
+                              }
+                         }
+                       if ((!sd->widget) || 
+                           (!elm_widget_drag_child_locked_y_get(sd->widget)))
+                         {
+                            pgy = _smart_page_y_get(sd, oy);
+                            if (pgy != y) 
+                              {
+                                 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
+                                 _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
+                              }
+                         }
+                    }
+              }
+             else
+               {
+                  sd->down.pdx = 0;
+                  sd->down.pdy = 0;
+                  if (_smart_do_page(sd))
+                    {
+                       Evas_Coord pgx, pgy;
+
+                       elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+                       if ((!sd->widget) || 
+                           (!elm_widget_drag_child_locked_x_get(sd->widget)))
+                         {
+                            pgx = _smart_page_x_get(sd, ox);
+                            if (pgx != x) _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
+                         }
+                       if ((!sd->widget) || 
+                           (!elm_widget_drag_child_locked_y_get(sd->widget)))
+                         {
+                            pgy = _smart_page_y_get(sd, oy);
+                            if (pgy != y) _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
+                         }
+                    }
+                  if (sd->down.hold_animator)
+                    {
+                       ecore_animator_del(sd->down.hold_animator);
+                       sd->down.hold_animator = NULL;
+                    }
+               }
+             if (sd->down.scroll)
+               {
+                  ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
+                  sd->down.scroll = 0;
+               }
+             if (sd->down.hold)
+               {
+                  ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+                  sd->down.hold = 0;
+               }
+             sd->down.dragged_began = 0;
+             sd->down.dir_x = 0;
+             sd->down.dir_y = 0;
+             sd->down.want_dragged = 0;
+            sd->down.dragged = 0;
+            sd->down.now = 0;
+             elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+             elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+             sd->wx = x;
+             sd->wy = y;
+             elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &sd->ww, &sd->wh);
+             if (!_smart_do_page(sd))
+               bounce_eval(sd);
+         }
+     }
+}
+
+static Eina_Bool
+_smart_onhold_animator(void *data)
+{
+   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_threshold * 2.0;
+        vy = sd->down.onhold_vy * td * (double)_elm_config->thumbscroll_threshold * 2.0;
+        elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
+        x = ox;
+        y = oy;
+        
+        if (sd->down.dir_x)
+          {
+             if ((!sd->widget) || 
+                 (!elm_widget_drag_child_locked_x_get(sd->widget)))
+               {
+                  sd->down.onhold_vxe += vx;
+                  x = ox + (int)sd->down.onhold_vxe;
+                  sd->down.onhold_vxe -= (int)sd->down.onhold_vxe;
+               }
+          }
+        
+        if (sd->down.dir_y)
+          {
+             if ((!sd->widget) || 
+                 (!elm_widget_drag_child_locked_y_get(sd->widget)))
+               {
+                  sd->down.onhold_vye += vy;
+                  y = oy + (int)sd->down.onhold_vye;
+                  sd->down.onhold_vye -= (int)sd->down.onhold_vye;
+               }
+          }
+        
+        elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+     }
+   sd->down.onhold_tlast = t;
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_smart_event_post_move(void *data, Evas *e __UNUSED__)
+{
+   Smart_Data *sd = data;
+
+   if (sd->down.want_dragged)
+     {
+        int start = 0;
+
+        if (sd->down.hold_parent)
+          {
+             if ((sd->down.dir_x) && !can_scroll(sd, sd->down.hdir))
+               {
+                  sd->down.dir_x = 0;
+               }
+             if ((sd->down.dir_y) && !can_scroll(sd, sd->down.vdir))
+               {
+                  sd->down.dir_y = 0;
+               }
+          }
+        if (sd->down.dir_x)
+          {
+             if ((!sd->widget) || 
+                 (!elm_widget_drag_child_locked_x_get(sd->widget)))
+               {
+                  sd->down.want_dragged = 0;
+                  sd->down.dragged = 1;
+                  if (sd->widget)
+                    {
+                       elm_widget_drag_lock_x_set(sd->widget, 1);
+                    }
+                  start = 1;
+               }
+             else
+               sd->down.dir_x = 0;
+          }
+        if (sd->down.dir_y)
+          {
+             if ((!sd->widget) || 
+                 (!elm_widget_drag_child_locked_y_get(sd->widget)))
+               {
+                  sd->down.want_dragged = 0;
+                  sd->down.dragged = 1;
+                  if (sd->widget)
+                    {
+                       elm_widget_drag_lock_y_set(sd->widget, 1);
+                    }
+                  start = 1;
+               }
+             else
+               sd->down.dir_y = 0;
+          }
+        if ((!sd->down.dir_x) && (!sd->down.dir_y))
+          {
+             sd->down.cancelled = 1;
+          }
+        if (start) _smart_drag_start(sd->smart_obj);
+     }
+   return EINA_TRUE;
+}
+
+static void
+_smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Evas_Event_Mouse_Move *ev;
+   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 (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->down.hold_parent = 1;
+   evas_post_event_callback_push(e, _smart_event_post_move, sd);
+   // FIXME: respect elm_widget_scroll_hold_get of parent container
+   if (_elm_config->thumbscroll_enable)
+     {
+       if (sd->down.now)
+         {
+             int dodir = 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;
+
+             if (!sd->down.dragged_began)
+               {
+                  x = ev->cur.canvas.x - sd->down.x;
+                  y = ev->cur.canvas.y - sd->down.y;
+                  
+                  sd->down.hdir = -1;
+                  sd->down.vdir = -1;
+                    
+                  if      (x > 0) sd->down.hdir = LEFT;
+                  else if (x < 0) sd->down.hdir = RIGHT;
+                  if      (y > 0) sd->down.vdir = UP;
+                  else if (y < 0) sd->down.vdir = DOWN;
+                  
+                  if (x < 0) x = -x;
+                  if (y < 0) y = -y;
+             
+                  if ((sd->one_dir_at_a_time) &&
+                      (!((sd->down.dir_x) || (sd->down.dir_y))))
+                    {
+                       if (x > _elm_config->thumbscroll_threshold)
+                         {
+                            if (x > (y * 2))
+                              {
+                                 sd->down.dir_x = 1;
+                                 sd->down.dir_y = 0;
+                                 dodir++;
+                              }
+                         }
+                       if (y > _elm_config->thumbscroll_threshold)
+                         {
+                            if (y > (x * 2))
+                              {
+                                 sd->down.dir_x = 0;
+                                 sd->down.dir_y = 1;
+                                 dodir++;
+                              }
+                         }
+                       if (!dodir)
+                         {
+                            sd->down.dir_x = 1;
+                            sd->down.dir_y = 1;
+                         }
+                    }
+                  else
+                    {
+//                       can_scroll(sd, LEFT);
+//                       can_scroll(sd, RIGHT);
+//                       can_scroll(sd, UP);
+//                       can_scroll(sd, DOWN);
+                       sd->down.dir_x = 1;
+                       sd->down.dir_y = 1;
+                    }
+               }
+             if ((!sd->hold) && (!sd->freeze))
+               {
+                  if ((sd->down.dragged) ||
+                      (((x * x) + (y * y)) >
+                       (_elm_config->thumbscroll_threshold *
+                        _elm_config->thumbscroll_threshold)))
+                    {
+                       sd->down.dragged_began = 1;
+                       if (!sd->down.dragged)
+                         {
+                            sd->down.want_dragged = 1;
+                            ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+//                            evas_event_feed_hold(e, 1, ev->timestamp, ev->data);
+//                            _smart_drag_start(sd->smart_obj);
+                         }
+                       if (sd->down.dragged)
+                         {
+                            ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+                         }
+//                       ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+//                       sd->down.dragged = 1;
+                       if (sd->down.dir_x)
+                         x = sd->down.sx - (ev->cur.canvas.x - sd->down.x);
+                       else
+                         x = sd->down.sx;
+                       if (sd->down.dir_y)
+                         y = sd->down.sy - (ev->cur.canvas.y - sd->down.y);
+                       else
+                         y = sd->down.sy;
+                       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) && (sd->down.dir_y)))
+                              {
+                                 if (sd->down.dir_x) y = sd->down.locked_y;
+                                 else x = sd->down.locked_x;
+                              }
+                         }
+                       if (_elm_config->thumbscroll_border_friction > 0.0)
+                         {
+                            Evas_Coord minx, miny;
+                            sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+                            if (y < miny)
+                               y += (miny - y) *
+                                  _elm_config->thumbscroll_border_friction;
+                            else if (sd->child.h <= sd->h)
+                               y += (sd->down.sy - y) *
+                                  _elm_config->thumbscroll_border_friction;
+                            else if ((sd->child.h - sd->h + miny) < y)
+                               y += (sd->child.h - sd->h + miny - y) *
+                                  _elm_config->thumbscroll_border_friction;
+                            if (x < minx)
+                               x += (minx - x) *
+                                  _elm_config->thumbscroll_border_friction;
+                            else if (sd->child.w <= sd->w)
+                               x += (sd->down.sx - x) *
+                                  _elm_config->thumbscroll_border_friction;
+                            else if ((sd->child.w - sd->w + minx) < x)
+                               x += (sd->child.w - sd->w + minx - x) *
+                                  _elm_config->thumbscroll_border_friction;
+                         }
+
+                       sd->down.hold_x = x;
+                       sd->down.hold_y = y;
+                       if (!sd->down.hold_animator)
+                         sd->down.hold_animator = 
+                            ecore_animator_add(_smart_hold_animator, sd);
+//                       printf("a %i %i\n", sd->down.hold_x, sd->down.hold_y);
+//                       _smart_onhold_animator(sd);
+//                       elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+                    }
+                  else
+                    {
+                       if (sd->down.dragged_began)
+                         {
+                            ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+                            if (!sd->down.hold)
+                              {
+                                 sd->down.hold = 1;
+                                 evas_event_feed_hold(e, 1, ev->timestamp, ev->data);
+                              }
+                         }
+                    }
+              }
+             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_threshold)
+                    {
+                       if (_elm_config->thumbscroll_threshold > 0.0)
+                         vx = -(double)(_elm_config->thumbscroll_threshold - x) /
+                         _elm_config->thumbscroll_threshold;
+                       else
+                         vx = -1.0;
+                    }
+                  else if (x > (ew - _elm_config->thumbscroll_threshold))
+                    {
+                       if (_elm_config->thumbscroll_threshold > 0.0)
+                         vx = (double)(_elm_config->thumbscroll_threshold - (ew - x)) /
+                         _elm_config->thumbscroll_threshold;
+                       else
+                         vx = 1.0;
+                    }
+                  if (y < _elm_config->thumbscroll_threshold)
+                    {
+                       if (_elm_config->thumbscroll_threshold > 0.0)
+                         vy = -(double)(_elm_config->thumbscroll_threshold - y) /
+                         _elm_config->thumbscroll_threshold;
+                       else
+                         vy = -1.0;
+                    }
+                  else if (y > (eh - _elm_config->thumbscroll_threshold))
+                    {
+                       if (_elm_config->thumbscroll_threshold > 0.0)
+                         vy = (double)(_elm_config->thumbscroll_threshold - (eh - y)) /
+                         _elm_config->thumbscroll_threshold;
+                       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);
+                            sd->down.onhold_animator = NULL;
+                         }
+                    }
+               }
+         }
+     }
+}
+
+static void
+_smart_scrollbar_read(Smart_Data *sd)
+{
+   Evas_Coord x, y, mx = 0, my = 0, px, py, minx = 0, miny = 0;
+   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);
+   sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+   x = vx * (double)mx + minx;
+   y = vy * (double)my + miny;
+   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(Smart_Data *sd)
+{
+   Evas_Coord px = 0, py = 0, minx = 0, miny = 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.min_get(sd->pan_obj, &minx, &miny);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   sd->pan_func.set(sd->pan_obj, minx, miny);
+   if ((px != minx) || (py != miny))
+     edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+}
+
+static int
+_smart_scrollbar_bar_v_visibility_adjust(Smart_Data *sd)
+{
+   int scroll_v_vis_change = 0;
+   Evas_Coord h, vw, vh;
+
+   h = sd->child.h;
+   evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
+   if (sd->vbar_visible)
+     {
+       if (sd->vbar_flags == ELM_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_SMART_SCROLLER_POLICY_OFF)
+         {
+            scroll_v_vis_change = 1;
+            sd->vbar_visible = 0;
+         }
+     }
+   else
+     {
+       if (sd->vbar_flags == ELM_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_SMART_SCROLLER_POLICY_ON)
+         {
+            scroll_v_vis_change = 1;
+            sd->vbar_visible = 1;
+         }
+     }
+   if (scroll_v_vis_change)
+     {
+        if (sd->vbar_flags != ELM_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(Smart_Data *sd)
+{
+   int scroll_h_vis_change = 0;
+   Evas_Coord w, vw, vh;
+
+   w = sd->child.w;
+   evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
+   if (sd->hbar_visible)
+     {
+       if (sd->hbar_flags == ELM_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_SMART_SCROLLER_POLICY_OFF)
+         {
+            scroll_h_vis_change = 1;
+            sd->hbar_visible = 0;
+         }
+     }
+   else
+     {
+       if (sd->hbar_flags == ELM_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_SMART_SCROLLER_POLICY_ON)
+         {
+            scroll_h_vis_change = 1;
+            sd->hbar_visible = 1;
+         }
+     }
+   if (scroll_h_vis_change)
+     {
+        if (sd->hbar_flags != ELM_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(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(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, minx = 0, miny = 0;
+       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);
+       sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+       x = vx * mx + minx;
+       y = vy * my + miny;
+
+       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, minx = 0, miny = 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.min_get(sd->pan_obj, &minx, &miny);
+       sd->pan_func.get(sd->pan_obj, &px, &py);
+       sd->pan_func.set(sd->pan_obj, minx, miny);
+        if ((px != minx) || (py != miny))
+         edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+     }
+   _smart_scrollbar_bar_visibility_adjust(sd);
+}
+
+static void
+_smart_reconfigure(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)
+{
+   Smart_Data *sd;
+   Evas_Object *o;
+
+   sd = calloc(1, sizeof(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_SMART_SCROLLER_POLICY_AUTO;
+   sd->vbar_flags = ELM_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;
+   sd->momentum_animator_disabled = 0;
+   sd->bounce_animator_disabled = 0;
+   
+   o = edje_object_add(evas_object_evas_get(obj));
+   evas_object_propagate_events_set(o, 0);
+   sd->edje_obj = o;
+   // FIXME: null parent obj ... :(
+   elm_smart_scroller_object_theme_set(NULL, obj, "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.min_get = _elm_smart_pan_min_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;
+   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_animator_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);
+   elm_smart_scroller_child_region_set(obj, sd->wx, sd->wy, sd->ww, sd->h);
+}
+
+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,
+               NULL,
+               NULL,
+               NULL
+         };
+       _smart = evas_smart_class_new(&sc);
+     }
+}
+
diff --git a/src/lib/els_scroller.h b/src/lib/els_scroller.h
new file mode 100644 (file)
index 0000000..4fe85fc
--- /dev/null
@@ -0,0 +1,39 @@
+typedef enum _Elm_Smart_Scroller_Policy
+{
+   ELM_SMART_SCROLLER_POLICY_AUTO,
+   ELM_SMART_SCROLLER_POLICY_ON,
+   ELM_SMART_SCROLLER_POLICY_OFF
+}
+Elm_Smart_Scroller_Policy;
+
+Evas_Object *elm_smart_scroller_add             (Evas *evas);
+void elm_smart_scroller_child_set               (Evas_Object *obj, Evas_Object *child);
+void 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_min_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 elm_smart_scroller_custom_edje_file_set    (Evas_Object *obj, char *file, char *group);
+void elm_smart_scroller_child_pos_set           (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+void elm_smart_scroller_child_pos_get           (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void elm_smart_scroller_child_region_show       (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+void elm_smart_scroller_child_region_set        (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+void elm_smart_scroller_child_viewport_size_get (Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
+void elm_smart_scroller_step_size_set           (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+void elm_smart_scroller_step_size_get           (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void elm_smart_scroller_page_size_set           (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+void elm_smart_scroller_page_size_get           (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void elm_smart_scroller_policy_set              (Evas_Object *obj, Elm_Smart_Scroller_Policy hbar, Elm_Smart_Scroller_Policy vbar);
+void elm_smart_scroller_policy_get              (Evas_Object *obj, Elm_Smart_Scroller_Policy *hbar, Elm_Smart_Scroller_Policy *vbar);
+Evas_Object *elm_smart_scroller_edje_object_get (Evas_Object *obj);
+void elm_smart_scroller_single_dir_set          (Evas_Object *obj, Eina_Bool single_dir);
+Eina_Bool elm_smart_scroller_single_dir_get     (Evas_Object *obj);
+void elm_smart_scroller_object_theme_set        (Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style);
+void elm_smart_scroller_hold_set                (Evas_Object *obj, Eina_Bool hold);
+void elm_smart_scroller_freeze_set              (Evas_Object *obj, Eina_Bool freeze);
+void elm_smart_scroller_bounce_allow_set        (Evas_Object *obj, Eina_Bool horiz, Eina_Bool vert);
+void elm_smart_scroller_bounce_allow_get        (const Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert);
+void elm_smart_scroller_paging_set              (Evas_Object *obj, double pagerel_h, double pagerel_v, Evas_Coord pagesize_h, Evas_Coord pagesize_v);
+void elm_smart_scroller_paging_get              (Evas_Object *obj, double *pagerel_h, double *pagerel_v, Evas_Coord *pagesize_h, Evas_Coord *pagesize_v);
+void elm_smart_scroller_region_bring_in         (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+void elm_smart_scroller_widget_set              (Evas_Object *obj, Evas_Object *wid);
+Eina_Bool elm_smart_scroller_momentum_animator_disabled_get   (Evas_Object *obj);
+void elm_smart_scroller_momentum_animator_disabled_set             (Evas_Object *obj, Eina_Bool disabled);
+void elm_smart_scroller_bounce_animator_disabled_set               (Evas_Object *obj, Eina_Bool disabled);
+Eina_Bool elm_smart_scroller_bounce_animator_disabled_get     (Evas_Object *obj);
diff --git a/src/lib/els_tooltip.c b/src/lib/els_tooltip.c
new file mode 100644 (file)
index 0000000..060f06f
--- /dev/null
@@ -0,0 +1,787 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Tooltips Tooltips
+ *
+ * The Tooltip is an (internal, for now) smart object used to show a
+ * content in a frame on mouse hover of objects(or widgets), with
+ * tips/information about them.
+ */
+
+static const char _tooltip_key[] = "_elm_tooltip";
+
+#define ELM_TOOLTIP_GET_OR_RETURN(tt, obj, ...)         \
+  Elm_Tooltip *tt;                                      \
+  do                                                    \
+    {                                                   \
+       if (!(obj))                                      \
+         {                                              \
+            CRITICAL("Null pointer: " #obj);            \
+            return __VA_ARGS__;                         \
+         }                                              \
+       tt = evas_object_data_get((obj), _tooltip_key);  \
+       if (!tt)                                         \
+         {                                              \
+            ERR("Object does not have tooltip: " #obj); \
+            return __VA_ARGS__;                         \
+         }                                              \
+    }                                                   \
+  while (0)
+
+struct _Elm_Tooltip
+{
+   Elm_Tooltip_Content_Cb   func;
+   Evas_Smart_Cb            del_cb;
+   const void              *data;
+   const char              *style;
+   Evas                    *evas;
+   Evas_Object             *eventarea, *owner;
+   Evas_Object             *tooltip, *content;
+   Ecore_Timer             *show_timer;
+   Ecore_Timer             *hide_timer;
+   Ecore_Job               *reconfigure_job;
+   struct {
+      Evas_Coord            x, y, bx, by;
+   } pad;
+   struct {
+      double                x, y;
+   } rel_pos;
+   double                   hide_timeout; /* from theme */
+   Eina_Bool                visible_lock:1;
+   Eina_Bool                changed_style:1;
+};
+
+static void _elm_tooltip_reconfigure(Elm_Tooltip *tt);
+static void _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt);
+static void _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt);
+static void _elm_tooltip_hide_anim_start(Elm_Tooltip *tt);
+static void _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt);
+static void _elm_tooltip_show_timer_stop(Elm_Tooltip *tt);
+static void _elm_tooltip_hide(Elm_Tooltip *tt);
+static void _elm_tooltip_data_clean(Elm_Tooltip *tt);
+
+
+static void
+_elm_tooltip_content_changed_hints_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   _elm_tooltip_reconfigure_job_start(data);
+}
+
+static void
+_elm_tooltip_content_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Tooltip *tt = data;
+   tt->content = NULL;
+   tt->visible_lock = EINA_FALSE;
+   _elm_tooltip_hide(tt);
+}
+
+static void
+_elm_tooltip_obj_move_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Tooltip *tt = data;
+   _elm_tooltip_reconfigure_job_start(tt);
+}
+
+static void
+_elm_tooltip_obj_resize_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Tooltip *tt = data;
+   _elm_tooltip_reconfigure_job_start(tt);
+}
+
+static void
+_elm_tooltip_obj_mouse_move_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Tooltip *tt = data;
+   _elm_tooltip_reconfigure_job_start(tt);
+}
+
+static void
+_elm_tooltip_show(Elm_Tooltip *tt)
+{
+   _elm_tooltip_show_timer_stop(tt);
+   _elm_tooltip_hide_anim_stop(tt);
+
+   if (tt->tooltip)
+     {
+        _elm_tooltip_reconfigure_job_start(tt);
+        return;
+     }
+   tt->tooltip = edje_object_add(tt->evas);
+   if (!tt->tooltip) return;
+
+   evas_object_layer_set(tt->tooltip, ELM_OBJECT_LAYER_TOOLTIP);
+
+   evas_object_event_callback_add
+     (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
+   evas_object_event_callback_add
+     (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
+   evas_object_event_callback_add
+     (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, _elm_tooltip_obj_mouse_move_cb, tt);
+
+   evas_object_pass_events_set(tt->tooltip, EINA_TRUE);
+   tt->changed_style = EINA_TRUE;
+   _elm_tooltip_reconfigure_job_start(tt);
+}
+
+static void
+_elm_tooltip_content_del(Elm_Tooltip *tt)
+{
+   if (!tt->content) return;
+
+   evas_object_event_callback_del_full
+     (tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+      _elm_tooltip_content_changed_hints_cb, tt);
+   evas_object_event_callback_del_full
+     (tt->content, EVAS_CALLBACK_DEL,
+      _elm_tooltip_content_del_cb, tt);
+   evas_object_del(tt->content);
+   tt->content = NULL;
+}
+
+
+static void
+_elm_tooltip_hide(Elm_Tooltip *tt)
+{
+   _elm_tooltip_show_timer_stop(tt);
+   _elm_tooltip_hide_anim_stop(tt);
+   _elm_tooltip_reconfigure_job_stop(tt);
+
+   if (!tt->tooltip) return;
+   if (tt->visible_lock) return;
+
+   _elm_tooltip_content_del(tt);
+
+   evas_object_event_callback_del_full
+     (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
+   evas_object_event_callback_del_full
+     (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
+   evas_object_event_callback_del_full
+     (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, _elm_tooltip_obj_mouse_move_cb, tt);
+
+   evas_object_del(tt->tooltip);
+   tt->tooltip = NULL;
+}
+
+static void
+_elm_tooltip_reconfigure_job(void *data)
+{
+   Elm_Tooltip *tt = data;
+   tt->reconfigure_job = NULL;
+   _elm_tooltip_reconfigure(data);
+}
+
+static void
+_elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt)
+{
+   if (!tt->reconfigure_job) return;
+   ecore_job_del(tt->reconfigure_job);
+   tt->reconfigure_job = NULL;
+}
+
+static void
+_elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt)
+{
+   if (tt->reconfigure_job) ecore_job_del(tt->reconfigure_job);
+   tt->reconfigure_job = ecore_job_add
+     (_elm_tooltip_reconfigure_job, tt);
+}
+
+static Eina_Bool
+_elm_tooltip_hide_anim_cb(void *data)
+{
+   Elm_Tooltip *tt = data;
+   tt->hide_timer = NULL;
+   _elm_tooltip_hide(tt);
+   return EINA_FALSE;
+}
+
+static void
+_elm_tooltip_hide_anim_start(Elm_Tooltip *tt)
+{
+   if (tt->hide_timer) return;
+   edje_object_signal_emit(tt->tooltip, "elm,action,hide", "elm");
+   tt->hide_timer = ecore_timer_add
+     (tt->hide_timeout, _elm_tooltip_hide_anim_cb, tt);
+}
+
+static void
+_elm_tooltip_hide_anim_stop(Elm_Tooltip *tt)
+{
+   if (!tt->hide_timer) return;
+   if (tt->tooltip)
+     edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
+   ecore_timer_del(tt->hide_timer);
+   tt->hide_timer = NULL;
+}
+
+static void
+_elm_tooltip_reconfigure(Elm_Tooltip *tt)
+{
+   Evas_Coord ox, oy, ow, oh, px, py, tx, ty, tw, th, cw, ch;
+   Evas_Coord eminw, eminh, ominw, ominh;
+   double rel_x, rel_y;
+   Eina_Bool inside_eventarea;
+
+   _elm_tooltip_reconfigure_job_stop(tt);
+
+   if (tt->hide_timer) return;
+   if (!tt->tooltip) return;
+   if (tt->changed_style)
+     {
+        const char *style = tt->style ? tt->style : "default";
+        const char *str;
+        if (!_elm_theme_object_set
+            (tt->owner, tt->tooltip, "tooltip", "base", style))
+          {
+             ERR("Could not apply the theme to the tooltip! style=%s", style);
+             evas_object_del(tt->tooltip);
+             tt->tooltip = NULL;
+             return;
+          }
+
+        tt->rel_pos.x = 0;
+        tt->rel_pos.y = 0;
+
+        tt->pad.x = 0;
+        tt->pad.y = 0;
+        tt->pad.bx = 0;
+        tt->pad.by = 0;
+        tt->hide_timeout = 0.0;
+
+        str = edje_object_data_get(tt->tooltip, "pad_x");
+        if (str) tt->pad.x = atoi(str);
+        str = edje_object_data_get(tt->tooltip, "pad_y");
+        if (str) tt->pad.y = atoi(str);
+
+        str = edje_object_data_get(tt->tooltip, "pad_border_x");
+        if (str) tt->pad.bx = atoi(str);
+        str = edje_object_data_get(tt->tooltip, "pad_border_y");
+        if (str) tt->pad.by = atoi(str);
+
+        str = edje_object_data_get(tt->tooltip, "hide_timeout");
+        if (str)
+          {
+             tt->hide_timeout = atof(str);
+             if (tt->hide_timeout < 0.0) tt->hide_timeout = 0.0;
+          }
+
+        evas_object_pass_events_set(tt->tooltip, EINA_TRUE);
+        tt->changed_style = EINA_FALSE;
+        if (tt->tooltip)
+          edje_object_part_swallow
+            (tt->tooltip, "elm.swallow.content", tt->content);
+
+        edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
+     }
+
+   if (!tt->content)
+     {
+        tt->content = tt->func((void *)tt->data, tt->owner);
+        if (!tt->content)
+          {
+             WRN("could not create tooltip content!");
+             evas_object_del(tt->tooltip);
+             tt->tooltip = NULL;
+             return;
+          }
+        evas_object_layer_set(tt->content, ELM_OBJECT_LAYER_TOOLTIP);
+        evas_object_pass_events_set(tt->content, EINA_TRUE);
+        edje_object_part_swallow
+          (tt->tooltip, "elm.swallow.content", tt->content);
+        evas_object_event_callback_add
+          (tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+           _elm_tooltip_content_changed_hints_cb, tt);
+        evas_object_event_callback_add
+          (tt->content, EVAS_CALLBACK_DEL,
+           _elm_tooltip_content_del_cb, tt);
+
+     }
+
+   evas_object_size_hint_min_get(tt->content, &ominw, &ominh);
+   edje_object_size_min_get(tt->tooltip, &eminw, &eminh);
+
+   if (ominw < eminw) ominw = eminw;
+   if (ominh < eminh) ominh = eminh;
+
+   if (ominw < 1) ominw = 10; /* at least it is noticeable */
+   if (ominh < 1) ominh = 10; /* at least it is noticeable */
+
+   edje_object_size_min_restricted_calc
+     (tt->tooltip, &tw, &th, ominw, ominh);
+
+   evas_output_size_get(tt->evas, &cw, &ch);
+   evas_pointer_canvas_xy_get(tt->evas, &px, &py);
+
+   evas_object_geometry_get(tt->eventarea, &ox, &oy, &ow, &oh);
+
+   inside_eventarea = ((px >= ox) && (py >= oy) &&
+                       (px <= ox + ow) && (py <= oy + oh));
+   if (inside_eventarea)
+     {
+        tx = px;
+        ty = py;
+
+        if (tx + tw + tt->pad.x < cw) tx += tt->pad.x;
+        if (ty + th + tt->pad.y < ch) ty += tt->pad.y;
+     }
+   else
+     {
+        tx = ox + (ow / 2) - (tw / 2);
+        if (ch < (th + oy + oh)) ty = oy - th;
+        else ty = oy + oh;
+     }
+
+   if (tt->pad.bx * 2 + tw < cw)
+     {
+        if (tx < tt->pad.bx) tx = tt->pad.bx;
+        else if (tx + tw >= cw - tt->pad.bx) tx = cw - tw - tt->pad.bx;
+     }
+
+   if (tt->pad.by * 2 + th < ch)
+     {
+        if (ty < tt->pad.by) ty = tt->pad.by;
+        else if (ty + th >= ch - tt->pad.by) ty = ch - th - tt->pad.by;
+     }
+
+   evas_object_move(tt->tooltip, tx, ty);
+   evas_object_resize(tt->tooltip, tw, th);
+   evas_object_show(tt->tooltip);
+
+   if (inside_eventarea)
+     {
+        rel_x = (px - tx) / (double)tw;
+        rel_y = (py - ty) / (double)th;
+     }
+   else
+     {
+        rel_x = (ox + (ow / 2) - tx) / (double)tw;
+        rel_y = (oy + (oh / 2) - ty) / (double)th;
+     }
+
+#define FDIF(a, b) (fabs((a) - (b)) > 0.0001)
+   if ((FDIF(rel_x, tt->rel_pos.x)) || (FDIF(rel_y, tt->rel_pos.y)))
+     {
+        Edje_Message_Float_Set *msg;
+
+        msg = alloca(sizeof(Edje_Message_Float_Set) + sizeof(double));
+        msg->count = 2;
+        msg->val[0] = rel_x;
+        msg->val[1] = rel_y;
+        tt->rel_pos.x = rel_x;
+        tt->rel_pos.y = rel_y;
+
+        edje_object_message_send(tt->tooltip, EDJE_MESSAGE_FLOAT_SET, 1, msg);
+     }
+#undef FDIF
+}
+
+static void
+_elm_tooltip_show_timer_stop(Elm_Tooltip *tt)
+{
+   if (!tt->show_timer) return;
+   ecore_timer_del(tt->show_timer);
+   tt->show_timer = NULL;
+}
+
+static Eina_Bool
+_elm_tooltip_timer_show_cb(void *data)
+{
+   Elm_Tooltip *tt = data;
+   tt->show_timer = NULL;
+   _elm_tooltip_show(tt);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_elm_tooltip_obj_mouse_in_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Tooltip *tt = data;
+
+   _elm_tooltip_hide_anim_stop(tt);
+
+   if ((tt->show_timer) || (tt->tooltip)) return;
+
+   tt->show_timer = ecore_timer_add
+     (_elm_config->tooltip_delay, _elm_tooltip_timer_show_cb, tt);
+}
+
+static void
+_elm_tooltip_obj_mouse_out_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Tooltip *tt = data;
+
+   if (tt->visible_lock) return;
+
+   if (!tt->tooltip)
+     {
+        _elm_tooltip_show_timer_stop(tt);
+        return;
+     }
+
+   _elm_tooltip_hide_anim_start(tt);
+}
+
+static void _elm_tooltip_obj_del_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj, void *event_info  __UNUSED__);
+
+static void
+_elm_tooltip_unset(Elm_Tooltip *tt)
+{
+   tt->visible_lock = EINA_FALSE;
+   _elm_tooltip_hide(tt);
+   _elm_tooltip_data_clean(tt);
+
+   if (tt->eventarea)
+     {
+        evas_object_event_callback_del_full
+          (tt->eventarea, EVAS_CALLBACK_MOUSE_IN,
+           _elm_tooltip_obj_mouse_in_cb, tt);
+        evas_object_event_callback_del_full
+          (tt->eventarea, EVAS_CALLBACK_MOUSE_OUT,
+           _elm_tooltip_obj_mouse_out_cb, tt);
+        evas_object_event_callback_del_full
+          (tt->eventarea, EVAS_CALLBACK_DEL, _elm_tooltip_obj_del_cb, tt);
+
+        evas_object_data_del(tt->eventarea, _tooltip_key);
+     }
+   if (tt->owner)
+     {
+        evas_object_event_callback_del_full
+          (tt->owner, EVAS_CALLBACK_DEL, _elm_tooltip_obj_del_cb, tt);
+        elm_widget_tooltip_del(tt->owner, tt);
+     }
+
+   eina_stringshare_del(tt->style);
+   free(tt);
+}
+
+static void
+_elm_tooltip_obj_del_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj, void *event_info  __UNUSED__)
+{
+   Elm_Tooltip *tt = data;
+   if (tt->eventarea == obj) tt->eventarea = NULL;
+   if (tt->owner == obj) tt->owner = NULL;
+   _elm_tooltip_unset(tt);
+}
+
+static Evas_Object *
+_elm_tooltip_label_create(void *data, Evas_Object *obj)
+{
+   Evas_Object *label = elm_label_add(obj);
+   if (!label)
+     return NULL;
+   elm_object_style_set(label, "tooltip");
+   elm_label_label_set(label, data);
+   return label;
+}
+
+static void
+_elm_tooltip_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   eina_stringshare_del(data);
+}
+
+static void
+_elm_tooltip_data_clean(Elm_Tooltip *tt)
+{
+   if (tt->del_cb) tt->del_cb((void *)tt->data, tt->owner, NULL);
+
+   _elm_tooltip_content_del(tt);
+
+   tt->data = NULL;
+   tt->del_cb = NULL;
+}
+
+/**
+ * Notify tooltip should recalculate its theme.
+ * @internal
+ */
+void
+elm_tooltip_theme(Elm_Tooltip *tt)
+{
+   if (!tt->tooltip) return;
+   tt->changed_style = EINA_TRUE;
+   _elm_tooltip_reconfigure_job_start(tt);
+}
+
+
+/**
+ * Set the content to be shown in the tooltip object for specific event area.
+ *
+ * Setup the tooltip to object. The object @a eventarea can have only
+ * one tooltip, so any previous tooltip data is removed. @p func(with
+ * @p data) will be called every time that need show the tooltip and
+ * it should return a valid Evas_Object. This object is then managed
+ * fully by tooltip system and is deleted when the tooltip is gone.
+ *
+ * This is an internal function that is used by objects with sub-items
+ * that want to provide different tooltips for each of them. The @a
+ * owner object should be an elm_widget and will be used to track
+ * theme changes and to feed @a func and @a del_cb. The @a eventarea
+ * may be any object and is the one that should be used later on with
+ * elm_object_tooltip apis, such as elm_object_tooltip_hide(),
+ * elm_object_tooltip_show() or elm_object_tooltip_unset().
+ *
+ * @param eventarea the object being attached a tooltip.
+ * @param owner the elm_widget that owns this object, will be used to
+ *        track theme changes and to be used in @a func or @a del_cb.
+ * @param func the function used to create the tooltip contents. The
+ *        @a Evas_Object parameters will receive @a owner as value.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_object_tooltip_unset() or the owner object @a obj
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is NULL.
+ *
+ * @internal
+ * @ingroup Tooltips
+ */
+void
+elm_object_sub_tooltip_content_cb_set(Evas_Object *eventarea, Evas_Object *owner, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
+{
+   Elm_Tooltip *tt = NULL;
+   Eina_Bool just_created;
+
+   EINA_SAFETY_ON_NULL_GOTO(owner, error);
+   EINA_SAFETY_ON_NULL_GOTO(eventarea, error);
+
+   if (!func)
+     {
+        elm_object_tooltip_unset(eventarea);
+        return;
+     }
+
+   tt = evas_object_data_get(eventarea, _tooltip_key);
+   if (tt)
+     {
+        if (tt->owner != owner)
+          {
+             if (tt->owner != eventarea)
+               evas_object_event_callback_del_full
+                 (tt->owner, EVAS_CALLBACK_DEL, _elm_tooltip_obj_del_cb, tt);
+
+             elm_widget_tooltip_del(tt->owner, tt);
+
+             if (owner != eventarea)
+               evas_object_event_callback_add
+                 (owner, EVAS_CALLBACK_DEL, _elm_tooltip_obj_del_cb, tt);
+
+             elm_widget_tooltip_add(tt->owner, tt);
+          }
+
+        if ((tt->func == func) && (tt->data == data) &&
+            (tt->del_cb == del_cb))
+          return;
+        _elm_tooltip_data_clean(tt);
+        just_created = EINA_FALSE;
+     }
+   else
+     {
+        tt = ELM_NEW(Elm_Tooltip);
+        if (!tt) goto error;
+
+        tt->owner = owner;
+        tt->eventarea = eventarea;
+        tt->evas = evas_object_evas_get(eventarea);
+        evas_object_data_set(eventarea, _tooltip_key, tt);
+
+        just_created = EINA_TRUE;
+
+        evas_object_event_callback_add
+          (eventarea, EVAS_CALLBACK_MOUSE_IN,
+           _elm_tooltip_obj_mouse_in_cb, tt);
+        evas_object_event_callback_add
+          (eventarea, EVAS_CALLBACK_MOUSE_OUT,
+           _elm_tooltip_obj_mouse_out_cb, tt);
+        evas_object_event_callback_add
+          (eventarea, EVAS_CALLBACK_DEL, _elm_tooltip_obj_del_cb, tt);
+
+        if (owner != eventarea)
+          evas_object_event_callback_add
+            (owner, EVAS_CALLBACK_DEL, _elm_tooltip_obj_del_cb, tt);
+
+        elm_widget_tooltip_add(tt->owner, tt);
+     }
+
+   tt->func = func;
+   tt->data = data;
+   tt->del_cb = del_cb;
+
+   if (!just_created) _elm_tooltip_reconfigure_job_start(tt);
+   return;
+
+ error:
+   if (del_cb) del_cb((void *)data, owner, NULL);
+}
+
+/**
+ * Force show tooltip of object
+ *
+ * @param obj Target object
+ *
+ * Force show the tooltip and disable hide on mouse_out.
+ * If another content is set as tooltip, the visible tooltip will hididen and
+ * showed again with new content.
+ * This can force show more than one tooltip at a time.
+ *
+ * @ingroup Tooltips
+ */
+EAPI void
+elm_object_tooltip_show(Evas_Object *obj)
+{
+   ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
+   tt->visible_lock = EINA_TRUE;
+   _elm_tooltip_show(tt);
+}
+
+/**
+ * Force hide tooltip of object
+ *
+ * @param obj Target object
+ *
+ * Force hide the tooltip and (re)enable future mouse interations.
+ *
+ * @ingroup Tooltips
+ */
+EAPI void
+elm_object_tooltip_hide(Evas_Object *obj)
+{
+   ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
+   tt->visible_lock = EINA_FALSE;
+   _elm_tooltip_hide_anim_start(tt);
+}
+
+/**
+ * Set the text to be shown in the tooltip object
+ *
+ * @param obj Target object
+ * @param text The text to set in the content
+ *
+ * Setup the text as tooltip to object. The object can have only one tooltip,
+ * so any previous tooltip data is removed.
+ * This method call internaly the elm_tooltip_content_cb_set().
+ *
+ * @ingroup Tooltips
+ */
+EAPI void
+elm_object_tooltip_text_set(Evas_Object *obj, const char *text)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   text = eina_stringshare_add(text);
+   elm_object_tooltip_content_cb_set
+     (obj, _elm_tooltip_label_create, text, _elm_tooltip_label_del_cb);
+}
+
+/**
+ * Set the content to be shown in the tooltip object
+ *
+ * Setup the tooltip to object. The object can have only one tooltip,
+ * so any previous tooltip data is removed. @p func(with @p data) will
+ * be called every time that need show the tooltip and it should
+ * return a valid Evas_Object. This object is then managed fully by
+ * tooltip system and is deleted when the tooltip is gone.
+ *
+ * @param obj the object being attached a tooltip.
+ * @param func the function used to create the tooltip contents.
+ * @param data what to provide to @a func as callback data/context.
+ * @param del_cb called when data is not needed anymore, either when
+ *        another callback replaces @func, the tooltip is unset with
+ *        elm_object_tooltip_unset() or the owner object @a obj
+ *        dies. This callback receives as the first parameter the
+ *        given @a data, and @c event_info is NULL.
+ *
+ * @ingroup Tooltips
+ */
+EAPI void
+elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
+{
+   elm_object_sub_tooltip_content_cb_set(obj, obj, func, data, del_cb);
+}
+
+/**
+ * Unset tooltip from object
+ *
+ * @param obj Target object
+ *
+ * Remove tooltip from object. The callback provided as del_cb to
+ * elm_object_tooltip_content_cb_set() will be called to notify it is
+ * not used anymore.
+ *
+ * @see elm_object_tooltip_content_cb_set()
+ *
+ * @ingroup Tooltips
+ */
+EAPI void
+elm_object_tooltip_unset(Evas_Object *obj)
+{
+   ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
+   _elm_tooltip_unset(tt);
+}
+
+/**
+ * Sets a different style for this object tooltip.
+ *
+ * @note before you set a style you should define a tooltip with
+ *       elm_object_tooltip_content_cb_set() or
+ *       elm_object_tooltip_text_set().
+ *
+ * @param obj an object with tooltip already set.
+ * @param style the theme style to use (default, transparent, ...)
+ */
+EAPI void
+elm_object_tooltip_style_set(Evas_Object *obj, const char *style)
+{
+   ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
+   if (!eina_stringshare_replace(&tt->style, style)) return;
+   elm_tooltip_theme(tt);
+}
+
+/**
+ * Get the style for this object tooltip.
+ *
+ * @param obj an object with tooltip already set.
+ * @return style the theme style in use, defaults to "default". If the
+ *         object does not have a tooltip set, then NULL is returned.
+ */
+EAPI const char *
+elm_object_tooltip_style_get(const Evas_Object *obj)
+{
+   ELM_TOOLTIP_GET_OR_RETURN(tt, obj, NULL);
+   return tt->style ? tt->style : "default";
+}
+
+/**
+ * Get the configured tooltip delay
+ *
+ * This gets the globally configured tooltip delay in seconds
+ *
+ * @return The tooltip delay
+ * @ingroup Tooltips
+ */
+EAPI double
+elm_tooltip_delay_get(void)
+{
+   return _elm_config->tooltip_delay;
+}
+
+/**
+ * Set the configured tooltip delay
+ *
+ * This sets the globally configured delay to tooltip
+ *
+ * @param delay The delay to show the tooltip
+ * @return EINA_TRUE if value is valid and setted
+ * @ingroup Tooltips
+ */
+EAPI Eina_Bool
+elm_tooltip_delay_set(double delay)
+{
+   if (delay < 0.0) return EINA_FALSE;
+   _elm_config->tooltip_delay = delay;
+   return EINA_TRUE;
+}
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
new file mode 100644 (file)
index 0000000..b00ad7e
--- /dev/null
@@ -0,0 +1,6 @@
+AUTOMAKE_OPTIONS     = 1.4 foreign
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = \
+test_entry \
+test_map
diff --git a/src/modules/test_entry/Makefile.am b/src/modules/test_entry/Makefile.am
new file mode 100644 (file)
index 0000000..7f7e05b
--- /dev/null
@@ -0,0 +1,32 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_builddir) \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/lib \
+-I$(top_builddir)/src/lib \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+@ELEMENTARY_CFLAGS@ \
+@ELEMENTARY_X_CFLAGS@ \
+@ELEMENTARY_FB_CFLAGS@ \
+@ELEMENTARY_WIN32_CFLAGS@ \
+@ELEMENTARY_WINCE_CFLAGS@ \
+@ELEMENTARY_EDBUS_CFLAGS@ \
+@ELEMENTARY_EFREET_CFLAGS@ \
+@ELEMENTARY_ETHUMB_CFLAGS@
+
+if ELEMENTARY_WINDOWS_BUILD
+AM_CPPFLAGS += -DELEMENTARY_BUILD
+endif
+
+pkgdir = $(libdir)/elementary/modules/test_entry/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = mod.c
+
+module_la_LIBADD = $(top_builddir)/src/lib/libelementary.la
+module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/src/modules/test_entry/mod.c b/src/modules/test_entry/mod.c
new file mode 100644 (file)
index 0000000..0b978e6
--- /dev/null
@@ -0,0 +1,36 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+// module api funcs needed
+EAPI int
+elm_modapi_init(void *m __UNUSED__)
+{
+   return 1; // succeed always
+}
+
+EAPI int
+elm_modapi_shutdown(void *m __UNUSED__)
+{
+   return 1; // succeed always
+}
+
+// module fucns for the specific module type
+EAPI void
+obj_hook(Evas_Object *obj)
+{
+   printf("hook: %p\n", obj);
+}
+
+EAPI void
+obj_unhook(Evas_Object *obj)
+{
+   printf("unhook: %p\n", obj);
+}
+
+EAPI void
+obj_longpress(Evas_Object *obj)
+{
+   printf("longpress: %p\n", obj);
+}
diff --git a/src/modules/test_map/Makefile.am b/src/modules/test_map/Makefile.am
new file mode 100644 (file)
index 0000000..d789ce9
--- /dev/null
@@ -0,0 +1,32 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_builddir) \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/lib \
+-I$(top_builddir)/src/lib \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+@ELEMENTARY_CFLAGS@ \
+@ELEMENTARY_X_CFLAGS@ \
+@ELEMENTARY_FB_CFLAGS@ \
+@ELEMENTARY_WIN32_CFLAGS@ \
+@ELEMENTARY_WINCE_CFLAGS@ \
+@ELEMENTARY_EDBUS_CFLAGS@ \
+@ELEMENTARY_EFREET_CFLAGS@ \
+@ELEMENTARY_ETHUMB_CFLAGS@
+
+if ELEMENTARY_WINDOWS_BUILD
+AM_CPPFLAGS += -DELEMENTARY_BUILD
+endif
+
+pkgdir = $(libdir)/elementary/modules/test_map/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = mod.c
+
+module_la_LIBADD = $(top_builddir)/src/lib/libelementary.la
+module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/src/modules/test_map/mod.c b/src/modules/test_map/mod.c
new file mode 100644 (file)
index 0000000..8b45ede
--- /dev/null
@@ -0,0 +1,50 @@
+#include <Elementary.h>
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+EAPI int 
+elm_modapi_init(void *m __UNUSED__) 
+{   
+   return 1; // succeed always
+}
+
+EAPI int 
+elm_modapi_shutdown(void *m __UNUSED__) 
+{
+   return 1; // succeed always
+}
+
+EAPI Eina_Bool
+obj_hook(Evas_Object *obj __UNUSED__)
+{
+   return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+obj_unhook(Evas_Object *obj __UNUSED__)
+{ 
+   return EINA_TRUE;
+}
+
+EAPI Eina_Bool 
+obj_convert_geo_into_coord(const Evas_Object *obj __UNUSED__, int zoom __UNUSED__, double lon __UNUSED__, double lat __UNUSED__, int size __UNUSED__, int *x __UNUSED__, int *y __UNUSED__)
+{
+   return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+obj_convert_coord_into_geo(const Evas_Object *obj __UNUSED__, int zoom __UNUSED__, int x __UNUSED__, int y __UNUSED__, int size __UNUSED__, double *lon __UNUSED__, double *lat __UNUSED__)
+{
+   return EINA_FALSE;
+}
+
+EAPI char*
+obj_url_request(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
+{
+   char buf[PATH_MAX];
+   snprintf(buf, sizeof(buf), "http://tile.openstreetmap.org/%d/%d/%d.png",
+            zoom, x, y);
+   return strdup(buf);
+}
+
diff --git a/tests/test_decl.sh b/tests/test_decl.sh
new file mode 100755 (executable)
index 0000000..ca86eba
--- /dev/null
@@ -0,0 +1,102 @@
+#!/bin/bash
+ret=0
+
+check(){
+    i=$1
+    shift
+    grep -h -B1 -10 -e "^$i(" $@ >eapi.decl
+    if [ $? != 0 ]; then
+        echo -e "\e[31;1mNOT IMPLEMENTED\e[m\t $i"
+        ret=1
+        return
+    fi
+    grep -qe "^--$" eapi.decl
+    if [ $? == 0 ]; then
+        echo -e "\e[31;1mMULTI IMPLEMENT\e[m\t $i"
+        ret=1
+        return
+    fi
+
+    head -1 eapi.decl | grep -qe '^EAPI'
+    if [ $? != 0 ];then
+        echo -e "\e[31;1mMISSING EAPI\e[m\t $i"
+        ret=1
+    fi
+
+    func=$(echo $i | grep -oe 'elm_\w\+')
+    ass=$(sed '2q;d' eapi.decl)
+
+    echo $i | grep -qe "^elm_object"
+    if [ $? == 0 ];then
+        rm eapi.decl
+        return
+    fi
+
+    echo $i | grep -qe "^elm_widget"
+    if [ $? == 0 ];then
+
+        echo $ass | grep -qe "elm_widget\w\+(\(const \)\?Evas_Object \*"
+        if [ $? == 0 ];then
+            tail -n9 eapi.decl | grep -q "\(API_ENTRY\|_elm_widget_is\)"
+            if [ $? != 0 ];then
+                echo -e "\e[31;1mMISSING CHECKER\e[m\t $i"
+                ret=1
+            fi
+            return
+        fi
+
+        echo $ass | grep -qe "elm_widget\w\+(\(const \)\?Elm_ \*"
+        if [ $? == 0 ];then
+            tail -n9 eapi.decl | grep -qe "ELM_WIDGET_ITEM_CHECK"
+            if [ $? != 0 ];then
+                echo -e "\e[31;1mMISSING CHECKER\e[m\t $i"
+                ret=1
+            fi
+            return
+        fi
+    fi
+
+    echo $ass | grep -qe "elm_\w\+_add"
+    if [ $? == 0 ];then
+        echo -e "\e[32;1m???\e[m\t $i"
+        return
+    fi
+
+    echo $ass | grep -qe "elm_\w\+(\(const \)\?Evas_Object \*"
+    if [ $? == 0 ];then
+        tail -n9 eapi.decl | grep -q "ELM_CHECK_WIDTYPE"
+        if [ $? != 0 ];then
+            echo -e "\e[31;1mMISSING CHECKER\e[m\t $i"
+            ret=1
+        fi
+        return
+    fi
+
+    echo $ass | grep -qe "elm_\w\+(\(const \)\?Elm_\w\+_Item \*"
+    if [ $? == 0 ];then
+        tail -n9 eapi.decl | grep -qe "ELM_\w\+_ITEM_.*CHECK"
+        if [ $? != 0 ];then
+            echo -e "\e[31;1mMISSING CHECKER\e[m\t $i"
+            ret=1
+        fi
+        return
+    fi
+
+    rm eapi.decl
+}
+
+grep -e "^ *EAPI.*(.*)" src/lib/Elementary.h.in | grep -oe 'elm_\w\+' >eapi.list
+
+for i in $(cat eapi.list); do
+    check $i $(ls -1 src/lib/*.c | grep -v elm_widget)
+done
+
+grep -e "^ *EAPI.*(.*)" src/lib/elm_widget.h | grep -oe '_\?elm_\w\+' >eapi.list
+
+for i in $(cat eapi.list); do
+    check $i src/lib/elm_widget.c
+done
+
+rm -f eapi.decl
+rm eapi.list
+exit $ret
diff --git a/tests/test_eapi.sh b/tests/test_eapi.sh
new file mode 100755 (executable)
index 0000000..4a190e5
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/bash
+ret=0
+
+sed -n '/^EAPI /{n;p;}' src/lib/*.c >eapi.list
+
+for i in $(cat eapi.list|grep -o "^\w\+"); do
+    grep -q "\<$i\>" src/lib/elm_priv.h
+    if [ $? == 0 ]; then
+        echo -e "\e[31;1mEAPI in priv.h\e[m\t $i"
+        ret=1
+    fi
+
+    echo $i | grep -qe '^_\?elm_widget'
+    if [ $? == 0 ]; then
+        grep -qe "EAPI.*\<$i\>" src/lib/elm_widget.h
+        if [ $? != 0 ]; then
+            echo -e "\e[31;1m WIDGET missing in widget.h\e[m\t $i"
+            ret=1
+        fi
+        grep -qe "EAPI.*\<$i\>" src/lib/Elementary.h.in
+        if [ $? == 0 ]; then
+            echo -e "\e[31;1m WIDGET in Elm.h\e[m\t $i"
+            ret=1
+        fi
+    else
+        grep -qe "EAPI.*\<$i\>" src/lib/Elementary.h.in
+        if [ $? != 0 ]; then
+            echo -e "\e[31;1m ELM missing in Elm.h\e[m\t $i"
+            ret=1
+        fi
+        grep -qe "EAPI.*\<$i\>" src/lib/elm_widget.h
+        if [ $? == 0 ]; then
+            echo -e "\e[31;1m ELM in widget.h\e[m\t $i"
+            ret=1
+        fi
+    fi
+done
+
+rm eapi.list
+exit $ret
diff --git a/tests/test_getter.sh b/tests/test_getter.sh
new file mode 100755 (executable)
index 0000000..749d488
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+ret=0
+check(){
+    func=$(echo $1 | grep -oe 'elm_\w\+')
+    echo $1 | grep -qe "_get([^\(const \)]\([^,\*)]\)\+\*"
+    if [ $? == 0 ];then
+        echo -e "\e[31;1mNOT CONST\e[m\t $func"
+        ret=1
+    fi
+
+}
+
+HEADERS="src/lib/Elementary.h.in
+src/lib/Elementary_Cursor.h
+src/lib/elm_widget.h"
+
+IFS=$'\n'
+
+for header in $HEADERS; do
+    grep -e "^ *EAPI.*(.*)" $header | grep -e 'elm_\w\+_get' >eapi.list
+
+    for i in $(cat eapi.list); do
+        check $i $header
+    done
+    rm eapi.list
+done
+exit $ret
diff --git a/tests/test_setter.sh b/tests/test_setter.sh
new file mode 100755 (executable)
index 0000000..eef7200
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/bash
+ret=0
+
+BLACKLIST="tests/test_setter_blacklist.txt"
+
+check(){
+    func=$(echo $1 | grep -oe '_\?elm_\w\+')
+    base=${func%_set}
+    cat $BLACKLIST | grep -q $func
+    if [ $? == 0 ];then
+       return
+    fi
+    echo $1 | grep -qe "_set(const \+[^\(char \+\*\)]"
+    if [ $? == 0 ];then
+        echo -e "\e[31;1mCONST\e[m\t $func"
+        ret=1
+    fi
+    echo $1 | grep -qe "EAPI \+\(void\|Eina_Bool\)"
+    if [ $? != 0 ];then
+        echo -e "\e[31;1mUNKNOWN RETURN\e[m\t $func"
+        ret=1
+    fi
+    echo $1 | grep -qe "\(cb_set\|all_set\)("
+    if [ $? != 0 ];then
+        grep -qe "EAPI.*\<${base}_get\>" $2
+        if [ $? != 0 ];then
+            echo -e "\e[31;1mMISSING GETTER\e[m\t $func"
+            ret=1
+        fi
+        echo $1 | grep -qe "\(content\|icon\|end\)_set(\w\+ \+\*obj, \w\+ \+\*\w\+);"
+        if [ $? == 0 ];then
+            grep -qe "EAPI.*\<${base}_unset\>" $2
+            if [ $? != 0 ];then
+                echo -e "\e[31;1mMISSING UNSETTER\e[m\t $func"
+                ret=1
+            fi
+        fi
+    fi
+}
+
+HEADERS="src/lib/Elementary.h.in
+src/lib/Elementary_Cursor.h
+src/lib/elm_widget.h"
+
+IFS=$'\n'
+
+for header in $HEADERS; do
+    grep -e "^ *EAPI.*(.*)" $header | grep -e 'elm_\w\+_set' >eapi.list
+
+    for i in $(cat eapi.list); do
+        check $i $header
+    done
+    rm eapi.list
+done
+exit $ret
diff --git a/tests/test_setter_blacklist.txt b/tests/test_setter_blacklist.txt
new file mode 100644 (file)
index 0000000..61e4501
--- /dev/null
@@ -0,0 +1,18 @@
+elm_widget_del_hook_set
+elm_widget_del_pre_hook_set
+elm_widget_focus_hook_set
+elm_widget_activate_hook_set
+elm_widget_disable_hook_set
+elm_widget_theme_hook_set
+elm_widget_event_hook_set
+elm_widget_changed_hook_set
+elm_widget_signal_emit_hook_set
+elm_widget_signal_callback_add_hook_set
+elm_widget_signal_callback_del_hook_set
+elm_widget_focus_next_hook_set
+elm_widget_on_focus_hook_set
+elm_widget_on_change_hook_set
+elm_widget_on_show_region_hook_set
+elm_widget_focus_region_hook_set
+elm_widget_on_focus_region_hook_set
+elm_radio_value_pointer_set